From 92a15c6e0f3352bef2f422066a2ee950a5941a1b Mon Sep 17 00:00:00 2001 From: filipagr Date: Wed, 11 Nov 2026 16:08:33 -0300 Subject: [PATCH] docs: match the docs to the console and API as of 2026-11-11 (audit 4) Fixes from the 2026-11-11 docs audit, checked against fil-one origin/main 6a972b29: - S3 compatibility: bucket versioning, default retention and encryption settings can't be granted to any key in either region; retention can be extended, not shortened; drop "Phase 2"/test-harness wording - JS presigned uploads need requestChecksumCalculation WHEN_REQUIRED; boto3 uses SigV4 explicitly; snippets read AWS_* env vars; Go and JS fragments compile; quickstarts run start to finish - Console pages: create-bucket Advanced settings, API key list and drawer, Organization sidebar group (beta flag removed), Support, Settings, Billing (Reactivate, Active badge), Get started - Billing: one trial per person, Owner reactivation, automatic charge - Warnings on destructive actions; first-request troubleshooting; limits - Both llms mirrors regenerated from the pages Co-Authored-By: Claude Opus 5.5 --- docs/app/api-keys.mdx | 33 +- docs/app/billing.mdx | 13 +- docs/app/buckets.mdx | 28 +- docs/app/dashboard.mdx | 14 +- docs/app/organization.mdx | 53 +- docs/app/settings.mdx | 19 +- docs/app/support.mdx | 21 +- docs/billing/trial.mdx | 20 +- docs/billing/usage.mdx | 4 +- docs/faq.mdx | 21 +- docs/introduction.mdx | 14 +- docs/limits.mdx | 23 +- docs/quickstart/cli.mdx | 19 +- docs/quickstart/index.mdx | 62 +- docs/quickstart/sdk.mdx | 61 +- docs/reference/errors.mdx | 10 + docs/reference/overview.mdx | 2 +- docs/reference/s3-compatibility.mdx | 55 +- docs/sdk/cli.mdx | 13 +- docs/sdk/go.mdx | 62 +- docs/sdk/javascript.mdx | 33 +- docs/sdk/overview.mdx | 8 +- docs/sdk/python.mdx | 25 +- docs/security/account-security.mdx | 2 + docs/security/api-keys.mdx | 36 +- docs/security/authentication.mdx | 42 +- docs/security/encryption.mdx | 6 +- docs/storage/buckets.mdx | 17 +- docs/storage/object-lock.mdx | 53 +- docs/storage/objects.mdx | 23 +- docs/storage/versioning.mdx | 4 +- docusaurus.config.js | 12 +- static/llms-full.txt | 3776 +++++++++++++++------------ static/llms.txt | 426 +-- 34 files changed, 2835 insertions(+), 2175 deletions(-) diff --git a/docs/app/api-keys.mdx b/docs/app/api-keys.mdx index 59f8620..8b9d0a0 100644 --- a/docs/app/api-keys.mdx +++ b/docs/app/api-keys.mdx @@ -16,18 +16,21 @@ The page has two tabs, **API keys** and **Connection details**. The table shows: | **Name** | The key name, with the Access Key ID underneath and a copy button | | **Region** | The region the key belongs to, such as `eu-west-1` (hidden on narrow screens) | | **Buckets** | **All Buckets**, or one badge per bucket the key is scoped to | -| **Permissions** | Badges for the object permissions, with the finer-grained ones grouped into **Data protection**, **Bucket management**, and **Bucket info** | +| **Permissions** | Badges for the object permissions (**Read**, **Write**, **List**, **Delete**), and a **+***n* badge for the rest. Open the key to see them all | | **Created by** | The member who created the key, and **Rotated by … on …** once it has been rotated. Shown when your organization has more than one member | -| **Status** | **Active** | -| **Last Used** | **Never** | +| **Status** | **Active**, or **Expired** once the key's expiry date has passed | | **⋯** | **Rotate** and **Delete**, for the keys you can act on | -With no keys yet the page reads **No API keys yet** and offers **Create your first key**. +With 5 or more keys, a **Search keys** box (by name or Access Key ID) and filters for region (**All regions**) and status (**All statuses**) appear above the table. + +Click a key's row to open its details: its **Status**, when it **Expires** (or **Never**), when it was **Created** and **Rotated**, its **Region**, which **Buckets** it reaches ("All buckets in this region" for an unscoped key), and its full **Object permissions** and **Bucket management** permissions. The details panel is the place to check a key's expiry date. + +With no keys yet the page reads **No API keys yet** and offers **Create your first key**. A Member sees "You can only see the keys you create. Owners and Admins see every key in the organization." instead, because the organization may hold keys they aren't shown. If your account is disabled, the **API Keys** page shows only a notice asking you to reactivate your subscription, with no keys, tabs, or **Create new key** button. -:::note Keep your own record of each key -**Last Used** and **Status** are placeholders for now: every key reads **Never** and **Active**, and the expiry date you set is not shown in this list. Note down what each key is for and when it expires, and give keys descriptive names so the **Name** column carries that context for you. +:::note Name keys for what uses them +The console doesn't show when a key was last used. Give each key a descriptive name, such as `backup-job-prod`, so you can tell from the list which application would break if you deleted it. ::: ## Who can manage keys @@ -38,7 +41,7 @@ What you can do here depends on your [role](/app/organization#roles-and-permissi - **Members** see, rotate, and delete only the keys they created themselves. - **Admins** and **Owners** see and manage every key in the organization. -A key can only carry permissions your role holds, and the form hides the ones it doesn't. **Set retention** and **Set legal hold** are Owner-only, so they appear only for Owners. If a member's role is narrowed, any key they created that the new role couldn't create is revoked, and removing a member revokes the keys they created. +A key can only carry permissions your role holds, and the form hides the ones it doesn't. **Set retention** and **Set legal hold** are Owner-only, so they appear only for Owners. If a member's role is narrowed, any key they created that the new role couldn't create is revoked, and removing a member revokes the keys they created. The member is emailed a list of the revoked keys. See [Organization](/app/organization#removing-a-member). ## Creating a key @@ -57,7 +60,7 @@ Click **Create new key**, which opens a dedicated page. | **List** | Browse and list objects | | **Delete** | Permanently remove objects | -**Read**, **Write**, and **List** are pre-selected. **Delete** is not. +**Read**, **Write**, and **List** are pre-selected. **Delete** is not. For a read-only key, untick **Write**: a key with **Write** can overwrite any object it reaches. Checking one of those reveals finer-grained permissions nested underneath it. These are granted individually, so tick the ones you need: @@ -76,7 +79,7 @@ A key with **Write** therefore needs **Set retention** ticked as well before it **Which buckets can this key access?** Defaults to **All buckets**, meaning every bucket in the key's region. Choose **Specific buckets** to pick from a list, filtered to the region you selected. -**When should it expire?** **Never expires** (the default), **30 days**, or **Custom** with a date picker. +**When should it expire?** **Never expires** (the default), **30 days**, or **Custom** with a date picker. A key with an expiry date works through the whole of that day (UTC) and stops at the start of the next one. Click **Create API key** to create it. @@ -84,6 +87,8 @@ Click **Create API key** to create it. On success a **Save your credentials** dialog shows the **Access Key ID** and the **Secret Access Key**, with the secret masked until you reveal it. You can copy either, or download the pair as a `.csv` or `.env` file. +A downloaded file holds the secret in plain text. Move the values into your password manager, secrets store, or your tool's credential file, then delete the download. Never commit it: if you keep a `.env` in a project, add it to `.gitignore` first. + :::warning The secret is shown once Fil One never stores your secret, which is why it appears only when a key is created or rotated. Copy or download it before closing the dialog. If you lose it, [rotate the key](#rotating-a-key) to get a new secret. ::: @@ -103,11 +108,15 @@ After a rotation, the **Created by** column shows who rotated the key and when. ## Revoking a key -Open the **⋯** menu on the key's row and choose **Delete**. The dialog warns that the key will be permanently revoked and that any application using it loses access immediately. +:::warning Deleting a key breaks anything that uses it +A deleted key stops working immediately and can't be restored. To move an application onto a key with different permissions or buckets, create the new key first, switch the application over, then delete the old one. +::: + +Open the **⋯** menu on the key's row and choose **Delete**. The dialog warns that the key will be permanently revoked and that any application using it loses access immediately. Deleting a key is how you revoke it. -Deleting a key is how you revoke it. To move an application onto a key with different permissions or buckets, create the new key first, switch the application over, then delete the old one. +To delete several keys at once, tick their checkboxes (or the header checkbox). A bar shows *n* **selected** with **Clear** and **Delete**. Only keys you're allowed to delete can be selected. -Revocation is confirmed with the storage operator before the key leaves your list, so a key that is still listed is a key that is still live. That ordering means the list stays a truthful picture of what has access. +A key stays in your list until its revocation is confirmed, so a key that is still listed is a key that still works. :::note Keys for a bucket A bucket's **API Keys** tab shows the keys that can reach that bucket, which is a quicker way to audit access for one bucket than reading down the full list. diff --git a/docs/app/billing.mdx b/docs/app/billing.mdx index 33184d8..f51aa07 100644 --- a/docs/app/billing.mdx +++ b/docs/app/billing.mdx @@ -3,7 +3,7 @@ title: Billing description: Reading the Fil One billing page, adding a payment method, and finding your invoices. --- -Billing is a page of its own, at `/billing`. Open it from **Billing** in the organization menu, at the top of the left sidebar (see [The organization menu](/app/organization#the-organization-menu)). +Billing is a page of its own, at `/billing`. Open it from **Billing** in the **Organization** group of the left sidebar (see [Where to find the organization's pages](/app/organization#where-to-find-the-organizations-pages)). Billing is visible to **Owners** and **Admins**. Every action on it (choosing or changing a plan, adding or updating a card, opening the Stripe portal) is for **Owners** only, so an Admin sees the same figures without the buttons. Members and Read only users see "Billing is managed by your organization's owners and admins" instead. See [Roles and permissions](/app/organization#roles-and-permissions). @@ -15,17 +15,20 @@ The **Plan** card names your plan and carries a status badge: | Status | Badge | Plan name and detail line | |--------|-------|---------------------------| -| Trial | **Trial** | **Free trial**, with how many days until the trial ends. The trial's storage and egress limits are on the [usage card](#usage) | -| Paid | **Active** | **Pay as you go**, with your per-TB rate and the renewal date | +| Trial | **Active** (blue) | **Free trial**. The trial's storage and egress limits are on the [usage card](#usage) | +| Paid | **Active** (green) | **Pay as you go**, with your per-TB rate and the renewal date | +| Billed manually | **Active** (green) | The name on your agreement, or **Custom plan**, with **Billed manually** | | Payment failed | **Payment failed** (amber) | Your plan name, rate, and renewal date, as for a paid plan | | Grace period | **Grace period** | Your plan name and rate, and how many days until access ends | | Canceled | **Canceled** | Your plan name and rate, and the date it was canceled | | No plan | None | **No plan**, with **Choose a plan to start storing data** | -If your plan was set up with the sales team, the card shows the name on your agreement, and **Custom pricing** where there is no single per-TB rate to show. +If your plan was set up with the sales team, the card shows the name on your agreement, and **Custom pricing** where there is no single per-TB rate to show. An organization billed manually by the sales team has no payment method to manage in the console. The button in this card is **Upgrade** on the trial, **Manage plan** on a paid plan (including one whose payment failed), **Reactivate** once the subscription is canceled, and **Choose a plan** during the grace period or with no plan. +A canceled subscription can be restarted at any time: an Owner clicks **Reactivate**, and the banner confirms "Your data is still here." Access returns as soon as the new subscription starts, without contacting support. + A banner above the cards flags a problem with the account: | Banner | Button | @@ -67,7 +70,7 @@ The **Payment method** card shows one of three things: **Update**, **Manage**, and **Manage plan** open the Stripe customer portal, where the card details are entered and stored. Fil One does not hold your card number. :::note Cancelling -Cancellation is handled in the Stripe portal, reached through **Manage plan**. +Cancellation is handled in the Stripe portal, reached through **Manage plan**, so only Owners can cancel. ::: ## Choosing a plan diff --git a/docs/app/buckets.mdx b/docs/app/buckets.mdx index d447f4c..ca00abe 100644 --- a/docs/app/buckets.mdx +++ b/docs/app/buckets.mdx @@ -19,24 +19,28 @@ Each row has an actions menu with **Browse objects**, **Copy bucket name**, **Co ### Deleting a bucket -Choose **Delete bucket** from the row's actions menu and confirm. Only empty buckets can be deleted: if the bucket still holds objects or object versions, the console says it is not empty and links to how to empty it. Use [Empty bucket](#emptying-a-bucket) first, then delete. Deletion is permanent. +:::warning Deleting a bucket can't be undone +A deleted bucket can't be restored, and applications that use it start failing straight away. +::: + +Choose **Delete bucket** from the row's actions menu and confirm. Only empty buckets can be deleted: if the bucket still holds objects or object versions, the console says it is not empty and links to how to empty it. Use [Empty bucket](#emptying-a-bucket) first, then delete. **Delete bucket** is only shown to Owners and Admins. It works in every region, including `eu-west-1`, where `DeleteBucket` is not available over the S3 API. See [Buckets](/storage/buckets#deleting-a-bucket). ## Creating a bucket -Click **Create bucket** and fill in: +Click **Create bucket** (or **New bucket** on the Dashboard) and fill in: -1. **Bucket name.** 3 to 63 characters, lowercase letters, numbers, and hyphens only, starting and ending with a letter or number. No dots, unlike AWS S3. Must be globally unique. +1. **Bucket name.** 3 to 63 characters, lowercase letters, numbers, and hyphens only, starting and ending with a letter or number. No dots, unlike AWS S3. The form says it "must be unique in this region". 2. **Region.** Europe (France) `eu-west-1`, the default, or US East (Michigan) `us-east-1`. This sets the endpoint you connect to. -3. **Object settings**, three switches that nest inside one another, all off by default: +3. **Advanced settings**, collapsed by default because most buckets don't need them. Expand it to set three switches that build on one another, all off by default: - **Versioning** keeps multiple versions of an object. - - **Object Lock** requires Versioning to be on, and stays greyed out until it is. - - **Retention** requires Object Lock, and stays greyed out until it is. Turning it on reveals a **Default Retention Policy** with **Governance** or **Compliance** mode (Governance by default) and a **Lock period** in **Days** or **Years**, defaulting to 15 days. The maximum is 100 years. + - **Object Lock** can't be turned on until Versioning is, and shows a **Needs Versioning** badge until then. + - **Retention** can't be turned on until Object Lock is, and shows a **Needs Object Lock** badge until then. Turning it on reveals a **Default Retention Policy** with **Governance** or **Compliance** mode (Governance by default) and a **Lock period** in **Days** or **Years**, defaulting to 15 days. The maximum is 100 years. -Turning a parent switch back off resets the ones nested inside it. + Turning a switch back off resets the ones that depend on it. While the section is collapsed, the line beside it lists what is on. -You can also expand **Create new key** to generate an access key alongside the bucket. It is pre-scoped to the bucket you are creating and to that bucket's region, and the submit button changes to **Create bucket and API key**. The secret is shown once, in a dialog. The console then opens the new bucket's page. +Click **Create bucket**. The console opens the new bucket, and its empty state offers **Create API key** (or **View API keys**, if you already have keys that reach it) so you can connect an application. A panel headed **Included by default** confirms two things you do not configure: all data is encrypted at rest, and every bucket is private, so access requires an API key. @@ -46,7 +50,7 @@ Name, region, versioning, Object Lock, and the default retention policy are all ## Inside a bucket -Opening a bucket shows its region, storage used, and creation time, then three property cards: **Versioning** and **Object Lock** (each **Enabled** or **Disabled**), and **Retention**, which shows the default retention policy, such as **Compliance · 15 days**, or **None**. Encryption is on for every bucket, so it has no card of its own. +Opening a bucket shows its region and storage used, then three property cards: **Versioning** and **Object Lock** (each **Enabled** or **Disabled**), and **Retention**, which shows the default retention policy, such as **Compliance · 15 days**, or **None**. Encryption is on for every bucket, so it has no card of its own. Once the bucket holds objects, **Empty bucket** and **Upload object** buttons appear in the header. While it is empty, the upload button sits in the empty state instead. @@ -61,7 +65,7 @@ The object table shows **Name**, **Size**, and **Last Modified**, plus **Version On a versioned bucket, a key with more than one version gets an expander and an *n* **versions** pill. Expanding shows the older versions, badged **Latest** for the current one and **Delete marker** where a delete marker sits on top. -Per-row icon buttons download or delete a single object. A checkbox on each row, and on the header, lets you select several at once. See [Deleting objects](#deleting-objects). +Per-row icon buttons download, share, or delete a single object. A checkbox on each row, and on the header, lets you select several at once. See [Deleting objects](#deleting-objects). :::note Large buckets The browser shows the first page of results, around 1,000 entries. When there are more, an amber **Showing the first** *n* notice appears, and selecting and deleting apply only to the objects listed. The count on the **Objects (N)** tab then comes from your bucket analytics, a daily reading that can lag recent changes, so expect it to be higher than the number of rows in view. Use the AWS CLI or an SDK to page through a full listing, or [Empty bucket](#emptying-a-bucket) to remove everything. See [Objects](/storage/objects). @@ -118,6 +122,10 @@ An object under an active retention period or legal hold is protected, and attem ### Emptying a bucket +:::danger Empty bucket permanently deletes everything in the bucket +It removes every object, every earlier version, and every delete marker that isn't protected by retention or a legal hold. It can't be undone, and versioning doesn't protect you: nothing is kept to restore from. +::: + **Empty bucket** on the bucket page removes every object in the bucket, including every earlier version and delete marker. Type the bucket name to confirm, then click **Delete everything**. The deletion runs on the server, so it is not limited to the objects listed on screen, and it keeps running if you close the dialog. When it finishes, the dialog reports **Bucket empty**, **Some objects remain** (with how many could not be deleted, for example because they are under active retention), or **Deletion stopped** if the job could not complete. diff --git a/docs/app/dashboard.mdx b/docs/app/dashboard.mdx index 603bda1..25962ac 100644 --- a/docs/app/dashboard.mdx +++ b/docs/app/dashboard.mdx @@ -3,21 +3,13 @@ title: Dashboard description: What the Fil One dashboard home page shows, and how to read its usage figures. --- -The dashboard at [app.filone.com](https://app.filone.com) is the home page of the console, reached from **Dashboard** at the top of the left sidebar. It summarises your plan, usage, and recent activity. A **New bucket** button sits in the header, and during the trial a banner shows the days left with an **Upgrade** button. +The dashboard at [app.filone.com](https://app.filone.com) is the home page of the console, reached from **Dashboard** at the top of the left sidebar. It summarises your plan, usage, and recent activity. A **New bucket** button sits in the header. During the trial, a **Free trial** banner shows the days left and an **Upgrade** button. You can dismiss it with its **×** button. For sign-in methods, email verification, two-factor authentication, and passkeys, see [Account Security](/security/account-security). -## Quick setup +## Get started -Until you have created a bucket, uploaded an object, and generated an API key, a **QUICK SETUP** card tracks your progress as *n* of 3. Each step turns green when it is done: - -| Step | Takes you to | -|------|--------------| -| **Create a bucket** | Your bucket list | -| **Upload an object** | Your bucket list, where you open a bucket and upload into it | -| **Generate API key** | The API keys page | - -The card disappears once all three are complete. +A new organization opens on a **Get started** page instead of the dashboard, because its dashboard would be all zeros. The page offers **Create bucket** and **Create API key**, which change to **Create another bucket** and **Create another key** once you have one. Below them, **Explore more** links to inviting your team, these docs, and the Fil One team. The page stays at `/get-started` if you want to come back to it. ## Plan, storage, and egress diff --git a/docs/app/organization.mdx b/docs/app/organization.mdx index 1a4c045..d78630f 100644 --- a/docs/app/organization.mdx +++ b/docs/app/organization.mdx @@ -1,34 +1,29 @@ --- title: Organization -description: The organization menu, members, roles, invitations, and the audit log for your Fil One organization. Beta. +description: Members, roles, invitations, billing access, and the audit log for your Fil One organization. --- -:::info Beta -Organizations are in **beta**. Inviting teammates is switched on by Fil One for selected organizations, so what you see on this page depends on whether yours is one of them. Details may change before general availability. -::: - -Every Fil One account starts as a one-person organization, with you as its **Owner**. Everything about the organization itself (its name and logo, who is in it, what it pays, and what has happened in it) is reached from the **organization menu** at the top of the left sidebar. +Every Fil One account starts as a one-person organization, with you as its **Owner**. You can invite teammates, give each one a role, and see what has changed in the organization. -## The organization menu +## Where to find the organization's pages -The organization's logo and name sit at the top of the left sidebar. Click them to open the menu, which lists the organization's pages. You only see the entries your role can open: +The organization's pages are in the **Organization** group of the left sidebar. You only see the entries your role can open: | Entry | What it opens | Who sees it | |-------|---------------|-------------| -| **Edit organization** | The organization's name and logo, and how to delete it (see [Editing the organization](#editing-the-organization)) | Owner, Admin | -| **Members** | Everyone in the organization, and pending invitations (see [Members](#members)) | Every role, beta only | +| **Members** | Everyone in the organization, and pending invitations (see [Members](#members)) | Every role | | **Billing** | Your plan, usage, payment method, and invoices (see [Billing](/app/billing)) | Owner, Admin | -| **Audit log** | A record of membership, key, and organization changes (see [Audit log](#audit-log)) | Owner, Admin, beta only | +| **Audit log** | A record of membership, key, and organization changes (see [Audit log](#audit-log)) | Owner, Admin | -Each is a page of its own, at `/edit-organization`, `/members`, `/billing`, and `/audit`. +The organization's logo and name sit at the top of the left sidebar. Click them to open the **organization menu**, which holds: -Below the pages, the menu lists your organizations if you belong to more than one (see [Switching organizations](#switching-organizations)), and, in the beta, **Create organization**. +- **Edit organization**, for Owners and Admins: the organization's name and logo, and how to delete it (see [Editing the organization](#editing-the-organization)) +- your organizations, if you belong to more than one (see [Switching organizations](#switching-organizations)) +- **Create organization**, for every role (see [Creating another organization](#creating-another-organization)) -While an organization has no active plan, every page except Settings, Edit organization, and Support is replaced by **Add a payment method to continue**, so **Members**, **Billing**, and **Audit log** are left out of the menu until a plan is in place. See [Billing](/app/billing). +Each page has its own address: `/edit-organization`, `/members`, `/billing`, and `/audit`. -## The organizations beta - -**Members**, **Audit log**, **Create organization**, and sending invitations are part of the organizations beta, which Fil One switches on for selected organizations. Outside the beta those entries don't appear, and opening `/members` or `/audit` directly takes you to the dashboard. **Edit organization** and **Billing** are available to every organization. To ask about access, email [support@filone.com](mailto:support@filone.com). +While an organization has no active plan, every page except Settings, Edit organization, and Support is replaced by **Add a payment method to continue**, and the sidebar's page links are hidden until a plan is in place. See [Billing](/app/billing). ## Editing the organization @@ -41,7 +36,11 @@ Members and Read only members who open the page see "Organization details are ma ## Creating another organization -In the beta, **Create organization** in the organization menu opens a dialog asking for an **Organization name**, with the same rules as above, and an optional logo. You become the new organization's Owner, and the console switches to it straight away. A new organization has its own members, keys, buckets, and billing, separate from the organization you created it from. +**Create organization** in the organization menu opens a dialog asking for an **Organization name**, with the same rules as above, and an optional logo. You become the new organization's Owner, and the console switches to it straight away. A new organization has its own members, keys, buckets, and billing, separate from the organization you created it from. You can own up to **10** organizations. Organizations you were invited into don't count toward that. + +:::warning A new organization has no free trial +Each person gets one [free trial](/billing/trial), on the first organization they own. An organization you create after that has no trial: it shows **Add a payment method to continue** until you add one, and it is billed separately, with its own monthly minimum. See [Pricing](/billing/pricing). +::: ## Roles and permissions @@ -85,7 +84,7 @@ The S3 API has no users or roles. A request made with an access key is allowed o ## Members -**Members** in the organization menu opens a page headed **Members**, "People with access to this organization." It has up to two tabs, each with a count beside its label: +**Members** in the sidebar opens a page headed **Members**, "People with access to this organization." It has up to two tabs, each with a count beside its label: | Tab | What it holds | Who sees it | |-----|---------------|-------------| @@ -110,14 +109,18 @@ With 5 or more members, a search box and a role filter appear above the table. Owners and Admins change a role from the picker in the **Role** column. The picker only offers roles you're allowed to assign: an Admin can move people between Admin, Member, and Read only, but can't change an Owner's role or make anyone an Owner. - **Making someone an Owner** asks you to confirm first, because they'll be able to manage billing, every member, and the organization itself, including removing you. -- **Moving someone to a role with fewer permissions** opens a preview of their access keys first. Any key that carries more than the new role allows is listed, and the confirm button becomes **Change role and revoke**. Those keys stop working straight away. To keep a client running, create a replacement key with the narrower permissions first, then change the role. Moving someone to Read only revokes every key they created, since Read only can't hold keys. +- **Moving someone to a role with fewer permissions** opens a preview of their access keys first. Any key that carries more than the new role allows is listed, and the confirm button becomes **Change role and revoke**. Those keys stop working straight away, and the member is emailed a list of them. To keep a client running, create a replacement key with the narrower permissions first, then change the role. Moving someone to Read only revokes every key they created, since Read only can't hold keys. - **Moving someone to a role with more permissions** takes effect immediately. You can change your own role too. The dialog warns you if the change takes away your ability to manage members or billing. ### Removing a member -Choose **Remove** from the row's **⋯** menu and confirm with **Remove member**. The person loses access to the organization, and **every access key they created is revoked**, so anything still using one stops working straight away. Invitations they sent that are still pending are withdrawn too. +:::warning Removing a member breaks their keys +Every access key the person created stops working the moment you confirm. If an application uses one of their keys, create a replacement key and switch the application to it first. +::: + +Choose **Remove** from the row's **⋯** menu and confirm with **Remove member**. The person loses access to the organization, and **every access key they created is revoked**, so anything still using one stops working straight away. Invitations they sent that are still pending are withdrawn too. The person is emailed a list of the keys that were revoked. Admins can remove Admins, Members, and Read only members. Only an Owner can remove an Owner. Owners and Admins can remove themselves. Members and Read only members can't remove themselves, so ask an Owner or Admin. @@ -139,7 +142,7 @@ Billing is not affected: the subscription belongs to the organization, not to th ## Invitations -Invitations are how anyone else joins your organization. Sending them needs an Owner or Admin role, and an organization in the beta. They're managed from the **Invitations** tab of the [Members](#members) page. +Invitations are how anyone else joins your organization. Sending them needs an Owner or Admin role. They're managed from the **Invitations** tab of the [Members](#members) page. ### Sending an invitation @@ -189,7 +192,7 @@ The **Organizations** section of [Settings](/app/settings) lists every organizat ## Audit log -**Audit log** in the organization menu opens a page, for Owners and Admins, that records changes to the organization: +**Audit log** in the sidebar opens a page, for Owners and Admins, that records changes to the organization: | Column | What it holds | |--------|---------------| @@ -202,7 +205,7 @@ Expand a row to see its details. Filter by date range (**From**, **To**), by eve Events recorded: -- Organization created, and organization renamed +- Organization created, organization renamed, and organization logo updated - Member invited, invitation revoked, and invitation accepted - Role changed, member removed, and ownership transferred - Key created, key deleted, and key rotated @@ -214,7 +217,7 @@ Events are kept for **90 days**. If you ask for a range that reaches further bac ## Billing -**Billing** in the organization menu opens the billing page, for Owners and Admins. See [Billing](/app/billing). +**Billing** in the sidebar opens the billing page, for Owners and Admins. See [Billing](/app/billing). ## Deleting an organization diff --git a/docs/app/settings.mdx b/docs/app/settings.mdx index 65ab539..feca3b2 100644 --- a/docs/app/settings.mdx +++ b/docs/app/settings.mdx @@ -7,22 +7,21 @@ description: Profile fields, your organizations, notification preferences, and a ## Profile -| Field | Rules | -|-------|-------| -| **Full name** | Cannot be empty, up to 200 characters | -| **Email** | Must be a valid address. Disposable addresses are rejected | +The **Profile** card holds your **Avatar**, **Name**, and **Email**. -**Save changes** stays disabled until you edit one of the fields, and a note beside it lists what will be saved. +- **Avatar**: upload a picture. It saves as soon as it uploads. +- **Name**: up to 200 characters, and can't be empty. It saves on its own when you click out of the field. There is no save button. +- **Email**: click the field to open **Change email**, enter the **New email**, and click **Update**. Disposable addresses are rejected. :::warning Changing your email address sends you back through verification -Saving a new address marks the account unverified, sends a verification email to the new address, and drops you straight onto the verification screen. Every page redirects there until you confirm, exactly as for a new account. +Updating the address marks the account unverified, sends a verification email to the new address, and drops you straight onto the verification screen. Every page redirects there until you confirm, exactly as for a new account. -You can edit the address again while unverified, so a typo is recoverable. +You can change the address again while unverified, so a typo is recoverable. ::: -**If you signed in with Google or GitHub, your name and email are managed there.** Both fields are read-only for social sign-ins, labelled *Managed by Google* or *Managed by GitHub* with a link straight to that provider's profile page, so you keep one source of truth for them. +**If you signed in with Google or GitHub, your name and email are managed there.** Avatar, name, and email are read-only for social sign-ins, labelled *Managed by Google* or *Managed by GitHub* with a link straight to that provider's profile page, so you keep one source of truth for them. -Your organization's name is not part of your profile. Owners and Admins rename it on the **Edit organization** page, opened from the organization menu at the top of the sidebar, where the name must be 2 to 100 characters, using letters, numbers, spaces, hyphens, and periods only. +Your organization's name is not part of your profile. Owners and Admins rename it on the **Edit organization** page, opened from the organization menu at the top of the left sidebar, where the name must be 2 to 100 characters, using letters, numbers, spaces, hyphens, and periods only. ## Organizations @@ -30,7 +29,7 @@ The **Organizations** section lists every organization you belong to, with your ## Notifications -**Marketing emails** ("Receive updates about new features") is a working toggle. It reflects your current subscription status, is off until you turn it on, and saves as soon as you flip it, with no **Save changes** button. +**Marketing emails** ("Receive updates about new features") is a working toggle. It reflects your current subscription status, is off until you turn it on, and saves as soon as you flip it. :::note Keep an eye on the trial caps There is no notification setting for uploads or storage limits. Keep an eye on the usage cards on the [Dashboard](/app/dashboard), which show your storage and egress against the trial caps. This is worth doing during the trial, where reaching a cap changes what the account can do. See [Usage](/billing/usage). diff --git a/docs/app/support.mdx b/docs/app/support.mdx index ba666bd..d69d326 100644 --- a/docs/app/support.mdx +++ b/docs/app/support.mdx @@ -3,31 +3,28 @@ title: Support description: How to reach the Fil One team from the console. --- -Support is reached from the user menu at the bottom of the left sidebar (your name and avatar), which offers **Settings**, **Support**, **Documentation**, and **Log out**. **Support** opens the support form. +**Support** and **Documentation** are at the bottom of the left sidebar, above your name. **Support** opens the support page. -## The support form +## The support page -The page is headed **Talk to an expert** and states that the team typically responds within one business day. - -Every field is required: +The page is headed **Support**, with "We typically respond within 1 business day" underneath. It has two fields: | Field | Notes | |-------|-------| -| **First name**, **Last name** | | -| **Company name** | | -| **Email** | The address the team replies to | -| **Category** | **Product Issue**, **Billing Issue**, **General Inquiry**, or **Feature Request** | +| **Category** | **Product issue**, **Billing issue**, **General inquiry**, or **Feature request** | | **Message** | What you need help with | -The form starts empty rather than pre-filling from your account, so enter the email address you would like the reply sent to. Submitting clears the form and confirms that the team will get back to you within one business day. +You don't enter your name, organization, or email: the console sends them with your message from your account. Under the form, "We'll reply to" shows the address the answer goes to. An **Email** field appears only if your account has no email address. Click **Send message**. The form clears and confirms that the team will get back to you within 1 business day. :::note Where the reply arrives -Your message creates a ticket for the support team, and they reply by email, so keep an eye on the address you entered rather than looking for a thread in the console. +Your message creates a ticket for the support team, and they reply by email to your account's address. Look for the reply in your inbox, not in the console. ::: +Below the form, **Common questions** answers a few frequent questions, such as whether buckets can be made public. The **More help** panel beside it links to these docs and offers **Report a bug**. + ## Other routes -- **Documentation** in the same user menu opens these docs in a new tab. +- **Documentation** at the bottom of the left sidebar opens these docs in a new tab. - The system status indicator links to the Fil One status page, which is the quickest way to check whether an issue is already known. On desktop it sits in the bar along the bottom of the content area; on a phone it is in the sidebar drawer. - Account deletion is handled over email at [support@filone.com](mailto:support@filone.com), as noted in [Settings](/app/settings). - For volume pricing, SLAs, or the Business plan, **Contact sales team** in the **Choose your plan** dialog on [Billing](/app/billing) reaches the sales team directly. On the trial or with no plan, **Talk to sales** in the **Need help?** panel beside the billing cards does the same. diff --git a/docs/billing/trial.mdx b/docs/billing/trial.mdx index 462bb05..11a715a 100644 --- a/docs/billing/trial.mdx +++ b/docs/billing/trial.mdx @@ -5,7 +5,9 @@ description: What is included in your free trial, and how billing works when you ## Free trial -Every new account starts with a 30-day free trial. No credit card is required. The trial starts once you have verified your email address, and each email address gets one trial. Members invited to someone else's organization do not get a trial of their own. +Every new account starts with a 30-day free trial. No credit card is required. The trial starts once you have verified your email address. + +Each person gets **one trial**, on the first organization they own. Changing your email address does not grant a second one. Members invited to someone else's organization do not get a trial of their own. An organization you create after your first has **no trial**: it needs a payment method before you can use it, and it is billed separately, with its own $5.99 / month minimum. | Included | Amount | |----------|--------| @@ -31,7 +33,9 @@ Trial egress is a **single cumulative budget** across the whole 30 days, not a m |-------|------|-----------------| | **Active trial** | 0-30 | Full access. Upload, download, manage data. | | **Grace period** | 31-37 | **Read-only.** Download your data and upgrade to a paid plan. No new uploads. | -| **Expired** | 38+ | Account disabled. No access to data, uploads, or API keys. | +| **Expired** | 38+ | Account disabled. No access to data, uploads, or API keys. An Owner can still reactivate from **Billing**. | + +The trial ends at the end of day 30, but the read-only state is applied by a job that runs twice a day (08:00 and 20:00 UTC). Uploads over the S3 API can keep working for up to about 12 hours after the trial ends, until that job runs. You will receive email reminders at: - **Day 15** -- Halfway through your trial, with an upgrade link. @@ -41,11 +45,11 @@ You will receive email reminders at: - **Day 38** -- Account disabled. :::note -You can upgrade to a paid plan at any time during the trial or grace period. Upgrading restores full access immediately. +You can upgrade to a paid plan at any time during the trial or grace period, and an organization Owner can reactivate from **Billing** after the account is disabled too. Upgrading or reactivating restores full access immediately. ::: :::info What "disabled" means -Disabling blocks all access to the account: your data is no longer reachable through the API or the dashboard, and access keys stop working. Fil One does not run an automatic purge at this point, so contact support if you need access restored or your data removed. +Disabling blocks all access to the account: your data is no longer reachable through the API or the dashboard, and access keys stop working. Fil One does not run an automatic purge at this point. To restore access, an organization Owner opens **Billing** and clicks **Reactivate**. To have your data removed, email [support@filone.com](mailto:support@filone.com). ::: ## Paid plan pricing @@ -60,11 +64,11 @@ Pricing is usage-based, measured as the average storage consumed across the bill ## Payment -Payments are processed through Stripe. An organization Owner adds a credit card from Billing in the dashboard, opened from **Billing** in the organization menu at the top of the left sidebar. See [Billing](/app/billing). +Payments are processed through Stripe. An organization Owner adds a credit card from Billing in the dashboard, opened from **Billing** under **Organization** in the left sidebar. See [Billing](/app/billing). - Invoices are generated monthly. - Usage details are visible on the Billing page to Owners and Admins. -- Payment is due on receipt of invoice. +- Each invoice is charged automatically to the card on file. ## Payment failures @@ -78,11 +82,11 @@ Don't rely on an email to tell you a payment has failed. If uploads stop working ## Cancellation -You can cancel your paid plan from the **Stripe billing portal**, which you open from **Billing** in the dashboard. When cancellation takes effect depends on the option you choose there: if you cancel at the end of the current billing period, your plan stays **active and billable until that period ends**. The **30-day grace period** begins only once Stripe actually cancels the subscription — not the moment you click cancel: +An organization Owner can cancel the paid plan from the **Stripe billing portal**, which opens from **Billing** in the dashboard. Admins can see usage on Billing but can't open the portal. When cancellation takes effect depends on the option you choose there: if you cancel at the end of the current billing period, your plan stays **active and billable until that period ends**. The **30-day grace period** begins only once Stripe actually cancels the subscription — not the moment you click cancel: | Phase | Duration | What you can do | |-------|----------|-----------------| | **Grace period** | 30 days | **Read-only.** Download your data or reactivate your plan. No new uploads. | | **Expired** | After grace period | Account disabled. No access to data, uploads, or API keys. | -Reactivating your plan during the grace period restores full access immediately. Once the account is disabled, contact support to restore access or to request removal of your data. +Reactivating restores full access immediately, during the grace period or after the account is disabled: an organization Owner opens **Billing** and clicks **Reactivate**. Reactivating starts a new subscription, so your billing date moves to the day you reactivate. To have your data removed instead, email [support@filone.com](mailto:support@filone.com). diff --git a/docs/billing/usage.mdx b/docs/billing/usage.mdx index c687376..c776a66 100644 --- a/docs/billing/usage.mdx +++ b/docs/billing/usage.mdx @@ -16,6 +16,8 @@ Storage is measured as an average rather than a peak — if you store 2 TB for h **On a paid plan, egress is not charged** — there are no egress fees. During the trial, egress is capped (see below). +You may see three egress figures. **Billing** shows egress for the current billing period. The **Dashboard** shows a rolling 30-day total. The trial cap counts egress cumulatively from the day the trial started. + ## Trial limits During the free trial, usage is capped at: @@ -30,6 +32,6 @@ If versioning is enabled on a bucket, every version of an object counts as store ## Billing period -Paid accounts are billed monthly. The billing period resets on the same day each month (the date you first upgraded from trial). Usage resets at the start of each new billing period. +Paid accounts are billed monthly. The billing period resets on the same day each month (the date you upgraded from the trial, or the date you last reactivated). Usage resets at the start of each new billing period. See [Trial & Billing](/billing/trial) for pricing details. diff --git a/docs/faq.mdx b/docs/faq.mdx index fb6fb57..c8f7638 100644 --- a/docs/faq.mdx +++ b/docs/faq.mdx @@ -9,7 +9,7 @@ description: Frequently asked questions about Fil One. Is Fil One S3-compatible?
-Yes. Fil One provides an S3-compatible API. Any application, SDK, or tool that works with AWS S3 works with Fil One by changing the endpoint URL to your region's endpoint — `https://s3.eu-west-1.filonecontent.com` or `https://s3.us-east-1.filonecontent.com`. See the [S3 Compatibility Reference](/reference/s3-compatibility) for the full list of supported operations. +Yes. Fil One provides an S3-compatible API, and the standard S3 SDKs and tools work with it once you make two changes: set the endpoint to your region's (`https://s3.eu-west-1.filonecontent.com` or `https://s3.us-east-1.filonecontent.com`), and turn on path-style addressing. Some S3 features are not available, such as bucket policies and lifecycle rules. Check the [S3 Compatibility Reference](/reference/s3-compatibility) for the operations your application uses.
@@ -35,13 +35,15 @@ Within a region, storage is fulfilled by a distributed network of storage provid
-What happens when I delete an object? +What happens when I delete an object or bucket?
On a bucket **without versioning**, the object disappears from your account immediately and there is no recycle bin or undo. On a bucket **with versioning enabled**, a delete over the S3 API without a version ID places a delete marker instead. The object stops appearing in listings, but every prior version is kept and can still be downloaded by version ID, and you can make the object visible again by deleting the delete marker. Those retained versions continue to count as stored storage. Deleting from the dashboard is different: it always removes the specific version you chose, permanently, and never writes a delete marker. See [Versioning](/storage/versioning). +Once deleted, an object is no longer accessible through the API or the dashboard. Because Filecoin stores data in sealed sectors, the underlying storage may persist for a bounded period until the sector naturally expires — an infrastructure detail set by the storage layer, not a user-facing state. That residual data stays encrypted, with key custody held by the regional storage operator rather than by you or Fil One (see [Encryption](/security/encryption)). The same applies when you delete a bucket. +
@@ -93,7 +95,9 @@ Path-style addressing is also required, and bucket names cannot contain dots. Ch What durability guarantees do you offer?
-Fil One is designed for high durability through distributed storage across multiple providers. Specific durability SLA details are available on request. +Fil One is designed for high durability through distributed storage across multiple providers. We don't publish a durability figure; for details, email [support@filone.com](mailto:support@filone.com). + +Availability is covered separately: the [Fil One SLA](https://www.filone.com/sla) commits to 99.9% monthly uptime, with service credits if it is missed.
@@ -102,7 +106,7 @@ Fil One is designed for high durability through distributed storage across multi Can multiple users access the same account?
-Yes, through organizations, which are in beta and not yet enabled for every account. An organization can have several members, each with a role: **Owner**, **Admin**, **Member**, or **Read only**. See [Organization](/app/organization) and [Roles and permissions](/app/organization#roles-and-permissions). +Yes, through organizations. An organization can have several members, each with a role: **Owner**, **Admin**, **Member**, or **Read only**. See [Organization](/app/organization) and [Roles and permissions](/app/organization#roles-and-permissions). Access through the S3 API is still per access key. There are no IAM users or bucket policies, so to share limited access with other services, create API keys scoped to specific buckets and permissions. @@ -120,13 +124,4 @@ Fil One does not currently expose per-object proof data — content identifiers,
-
-What happens to my data if I delete it? -
- -When you delete an object or bucket, it is immediately removed from your Fil One account and is no longer accessible via the API or dashboard. Because Filecoin stores data in sealed sectors, the underlying storage may persist for a bounded period until the sector naturally expires — an infrastructure detail set by the storage layer, not a user-facing state. That residual data stays encrypted, with key custody held by the regional storage operator rather than by you or Fil One (see [Encryption](/security/encryption)). The data is inaccessible through Fil One from the moment of deletion. - -
-
- diff --git a/docs/introduction.mdx b/docs/introduction.mdx index 9803423..f34f7c0 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -4,19 +4,21 @@ description: S3 object storage built for the AI era. slug: / --- -Fil One is an S3-compatible object storage platform designed for teams that need reliable, cost-effective storage with built-in compliance features. If you've used AWS S3, you already know how to use Fil One. +import Link from '@docusaurus/Link'; + +Fil One is an S3-compatible object storage platform designed for teams that need reliable, cost-effective storage, with Object Lock for write-once retention. If you've used AWS S3, you already know how to use Fil One. ## Get started -
- QuickstartGo from signup to your first upload in under 5 minutes. - S3 CompatibilitySee which S3 operations are supported and how to connect. - SDK ExamplesCopy-paste code examples for Python, JavaScript, Go, and CLI. +
+ QuickstartGo from signup to your first upload. + S3 CompatibilitySee which S3 operations are supported and how to connect. + SDK ExamplesCopy-paste code examples for Python, JavaScript, Go, and CLI.
## Why Fil One -**S3-compatible from day one.** Use the tools you already know — AWS CLI, boto3, any S3-compatible SDK. Point your existing code at our endpoint and it works. +**S3-compatible from day one.** Use the tools you already know — AWS CLI, boto3, any S3-compatible SDK. Point your existing code at your region's endpoint, turn on path-style addressing, and it works. See [S3 Compatibility](/reference/s3-compatibility) for the operations Fil One does not support. **Backed by Filecoin.** Fil One stores your data on Filecoin, a distributed storage network where storage providers must continuously submit cryptographic proofs that they are still holding the data they committed to store, or face penalties. diff --git a/docs/limits.mdx b/docs/limits.mdx index 32b0bd1..308f144 100644 --- a/docs/limits.mdx +++ b/docs/limits.mdx @@ -3,18 +3,20 @@ title: Limits & Quotas description: Service limits, quotas, and constraints. --- -## Account limits +## Organization limits | Limit | Trial | Paid | |-------|-------|------| | Storage | 1 TB (1,000 GB) | No limit | | Egress bandwidth | 2 TB (cumulative over the trial) | No limit | | API operations | Unlimited | Unlimited | -| Buckets per account | — | 100 in `eu-west-1`, 300 in `us-east-1` | +| Buckets per organization | Not confirmed | 100 in `eu-west-1`, 300 in `us-east-1` | During the trial these two caps behave differently: reaching the **storage** cap **write-locks** the account (reads still work), while reaching the **egress** cap **disables** it entirely. Trial egress is a single cumulative budget for the whole 30 days, not a monthly amount that resets. See [Trial & Billing](/billing/trial). -The bucket limit is provisioned per account rather than fixed by plan, and it differs by region. On a **paid** plan it is **100 buckets in `eu-west-1`** and **300 in `us-east-1`**. Contact support if you need a higher limit. +The bucket limit is provisioned per organization rather than fixed by plan, and it differs by region. On a **paid** plan it is **100 buckets in `eu-west-1`** and **300 in `us-east-1`**. To ask for a higher limit, email [support@filone.com](mailto:support@filone.com). + +Each person can own up to **10 organizations**, and each organization can have up to **25 pending invitations** at a time. See [Organization](/app/organization). The trial lasts 30 days. After it ends, your account enters a 7-day read-only grace period. If you do not upgrade before the grace period ends, the account is disabled and access is blocked. See [Trial & Billing](/billing/trial) for the full timeline and email schedule. @@ -36,6 +38,18 @@ The **dashboard** rejects object keys longer than **1,024 characters** when you For objects larger than 5 GB, use [multipart upload](/storage/multipart-uploads). +## Console limits + +These apply in the [console](/app/buckets) at app.filone.com, in both regions. They are set in the console, so they don't apply to requests you make with an S3 SDK or the AWS CLI. + +| Limit | Value | +|-------|-------| +| File size for a console upload | 5 GB. The console uploads each file in a single request. Use the [AWS CLI](/sdk/cli) or an SDK for larger files. | +| Tags per console upload | 50, up to 128 characters each | +| Description per console upload | 1,000 characters | +| Share link expiry | 7 days at most | +| Default retention on a bucket | 1 day to 100 years (36,500 days) | + ## Regions | Region | Identifier | Status | @@ -49,7 +63,7 @@ Bucket creation and deletion through the S3 API are available in `us-east-1` but ## API rate limits -Rate limits are enforced by the underlying storage gateway. Fil One does not impose additional rate limits on top of these. If you encounter `SlowDown` or `ServiceUnavailable` responses, back off with exponential retry. Contact support if you are consistently hitting limits at scale. +Rate limits are enforced by the underlying storage gateway. Fil One does not impose additional rate limits on top of these. If you encounter `SlowDown` or `ServiceUnavailable` responses, back off with exponential retry. If you consistently hit limits at scale, email [support@filone.com](mailto:support@filone.com). ## Naming constraints @@ -57,6 +71,7 @@ Rate limits are enforced by the underlying storage gateway. Fil One does not imp - 3-63 characters - Lowercase letters, numbers, hyphens (no dots — Fil One's naming rules are stricter than AWS S3 here) - Must start and end with a letter or number +- Must not start with `filone-rag-`, which is reserved - Unique within Fil One **Object keys:** diff --git a/docs/quickstart/cli.mdx b/docs/quickstart/cli.mdx index ba37ec4..e53e7d6 100644 --- a/docs/quickstart/cli.mdx +++ b/docs/quickstart/cli.mdx @@ -3,11 +3,11 @@ title: Quickstart - AWS CLI description: Upload your first object using the AWS CLI. --- -If you have the AWS CLI installed, you can start using Fil One in under 2 minutes. +Use the AWS CLI to upload, list and download objects in a Fil One bucket. You need a Fil One account and an API key. To create a key, open **API Keys** in the [console](https://app.filone.com), click **Create new key**, and pick the same region as your bucket. The secret is shown once. ## 1. Install the AWS CLI -Use **AWS CLI v2** — v1 does not read `endpoint_url` from config files: +Use **AWS CLI v2**, version 2.13 or later, so the CLI reads `endpoint_url` from your profile: ```bash brew install awscli @@ -17,7 +17,7 @@ brew install awscli ## 2. Configure credentials -Set up a named profile so you don't have to pass `--endpoint-url` on every command: +Set up a named profile, so you don't overwrite your default AWS credentials and don't have to pass `--endpoint-url` on every command: ```ini # ~/.aws/config @@ -45,7 +45,7 @@ aws_secret_access_key = YOUR_SECRET_KEY ## 3. Create a bucket -Whether `CreateBucket` works through the S3 API depends on the region. It is **not** available in `eu-west-1`, the default region — there, create buckets from the [Fil One dashboard](https://app.filone.com) by going to **Buckets → Create bucket**, entering a name, and clicking **Create bucket**. +Whether `CreateBucket` works through the S3 API depends on the region. It is **not** available in `eu-west-1`, the default region. There, create the bucket in the [Fil One console](https://app.filone.com): click **New bucket**, enter `my-bucket` (or your own name), and click **Create bucket**. In `us-east-1` you can create a bucket from the CLI, using a key that has the `CreateBucket` permission. This requires a `us-east-1` profile — define one the same way as the `filone` profile above but with the `us-east-1` endpoint and region (shown here as `filone-us`): @@ -53,24 +53,25 @@ In `us-east-1` you can create a bucket from the CLI, using a key that has the `C aws s3 mb s3://my-bucket --profile filone-us ``` -Creating from the dashboard is worth doing regardless, since that is where you set versioning and Object Lock — both are fixed at creation. See [Buckets](/storage/buckets). +Versioning and Object Lock can only be turned on when you create the bucket in the console. See [Buckets](/storage/buckets). -Once the bucket exists, use the AWS CLI for all object operations. +The steps below use the `filone` profile (`eu-west-1`). If your bucket is in `us-east-1`, use `--profile filone-us` instead: the profile, the key and the bucket must all be in the same region. ## 4. Upload a file ```bash -aws s3 cp my-file.txt s3://my-first-bucket/ --profile filone +echo "hello" > my-file.txt +aws s3 cp my-file.txt s3://my-bucket/ --profile filone ``` ## 5. List objects ```bash -aws s3 ls s3://my-first-bucket/ --profile filone +aws s3 ls s3://my-bucket/ --profile filone ``` ## 6. Download the file ```bash -aws s3 cp s3://my-first-bucket/my-file.txt ./downloaded.txt --profile filone +aws s3 cp s3://my-bucket/my-file.txt ./downloaded.txt --profile filone ``` diff --git a/docs/quickstart/index.mdx b/docs/quickstart/index.mdx index c16db7d..f88e939 100644 --- a/docs/quickstart/index.mdx +++ b/docs/quickstart/index.mdx @@ -1,6 +1,6 @@ --- title: Quickstart -description: Go from zero to your first upload in under 5 minutes. +description: Create an account, a bucket and an API key, then upload your first object from the console, the AWS CLI, Python or JavaScript. --- import Tabs from '@theme/Tabs'; @@ -11,45 +11,30 @@ This guide walks you through creating an account, setting up credentials, and up ## 1. Create your account -1. Go to [app.filone.com](https://app.filone.com) and sign up with your email or SSO. +1. Go to [app.filone.com](https://app.filone.com) and sign up with your email, Google, or GitHub. 2. Verify your email address. 3. You're in. No credit card needed — your 30-day free trial starts automatically. ## 2. Create a bucket -From the dashboard, click **New bucket** to open your buckets, then **Create bucket**. Give it a name (lowercase letters, numbers, and hyphens — note that Fil One does **not** allow dots, unlike AWS S3) and choose your settings: +From the dashboard, click **New bucket** to open the create form. Give the bucket a name (lowercase letters, numbers, and hyphens; unlike AWS S3, Fil One does **not** allow dots) and pick a region: | Setting | Options | Notes | |---------|---------|-------| | Region | `eu-west-1` Europe (France) or `us-east-1` US East (Michigan) | Defaults to `eu-west-1`. Cannot be changed later. | -| Encryption | Always on | All data is encrypted at rest by default. Nothing to configure. | -| Versioning | Off by default | Keeps a history of every version of an object. | -| Object Lock | Off by default | WORM protection. Requires versioning. | -| Retention | Off by default | A default retention period applied to new objects. Requires Object Lock. | +| Encryption | Always on | All data is encrypted at rest. Nothing to configure. | -:::warning These settings are permanent -Region, versioning, Object Lock, and retention are all fixed **at creation**. There is no way to turn versioning or Object Lock on for an existing bucket, or to move a bucket to another region — you would have to create a new bucket and copy your data across. If you think you will want version history or WORM protection, enable it now. -::: - -The three object settings nest, so you enable them in order: - -1. **Versioning** — turn this on first. Object Lock stays greyed out until you do. -2. **Object Lock** — becomes available once versioning is on. Retention stays greyed out until you enable it. -3. **Retention** — becomes available once Object Lock is on. Choose a mode and a duration: - - **Governance** (the default): in standard S3, a caller with a bypass permission can override it. Fil One does not currently expose a grantable bypass permission, so in practice protected objects cannot be deleted or modified until the retention period expires. See [Object Lock](/storage/object-lock). - - **Compliance**: no one can delete or modify objects until the retention period expires. - - The duration can be set in days or years, from 1 day up to 100 years. +Leave everything else at its default for your first bucket, and click **Create bucket**. -See [Versioning](/storage/versioning) and [Object Lock](/storage/object-lock) for the full picture before committing to either. - -You will also see an optional **API key** section during bucket creation. Expand it to create a new key scoped to this bucket in one step. If you plan to use the CLI or SDK, set up your key at this step — otherwise skip it and go to **API Keys** in the left menu later. Note that a key belongs to a single region, so it must match the region you picked above. +:::warning Some settings can only be chosen now +Versioning, Object Lock, and retention sit under **Advanced settings** on the create form, and can only be turned on when the bucket is created. Neither can be turned off later, and Object Lock can stop you deleting data you're paying for. Read [Versioning](/storage/versioning) and [Object Lock](/storage/object-lock) before you enable them on a bucket you plan to keep. +::: ## 3. Upload your first object -Choose your preferred method. The App requires no API key. For CLI and SDK access, go to **API Keys** in the left menu and click **Create new key**. You'll get two values: +Choose your preferred method. The App requires no API key. For CLI and SDK access, open your new bucket and click **Create API key**, or go to **API Keys** in the left menu and click **Create new key**. You'll get two values: -- **Access Key ID** — identifies your account (safe to store in config) +- **Access Key ID** — identifies the key (safe to store in config) - **Secret Access Key** — authenticates your requests (treat like a password) :::note @@ -69,31 +54,33 @@ The examples below use `eu-west-1`, the default region. For a bucket in `us-east - Configure the CLI to point at Fil One: + Create a `filone` profile so you don't overwrite your default AWS credentials. Requires [AWS CLI v2](/sdk/cli). Enter your key's ID and secret when prompted, and leave the other prompts empty: ```bash - aws configure set aws_access_key_id YOUR_ACCESS_KEY - aws configure set aws_secret_access_key YOUR_SECRET_KEY - aws configure set default.region eu-west-1 - # Path-style is required — Fil One does not support virtual-hosted URLs - aws configure set default.s3.addressing_style path + aws configure --profile filone + aws configure set region eu-west-1 --profile filone + aws configure set endpoint_url https://s3.eu-west-1.filonecontent.com --profile filone + # Path-style is required: Fil One does not support virtual-hosted URLs + aws configure set s3.addressing_style path --profile filone ``` Upload a file: ```bash - aws s3 cp my-file.txt s3://my-bucket/my-file.txt \ - --endpoint-url https://s3.eu-west-1.filonecontent.com + echo "hello" > my-file.txt + aws s3 cp my-file.txt s3://my-bucket/my-file.txt --profile filone ``` Verify it's there: ```bash - aws s3 ls s3://my-bucket/ --endpoint-url https://s3.eu-west-1.filonecontent.com + aws s3 ls s3://my-bucket/ --profile filone ``` + Create `my-file.txt` first, for example with `echo "hello" > my-file.txt`. + ```python import boto3 from botocore.config import Config @@ -104,7 +91,7 @@ The examples below use `eu-west-1`, the default region. For a bucket in `us-east aws_access_key_id="YOUR_ACCESS_KEY", aws_secret_access_key="YOUR_SECRET_KEY", region_name="eu-west-1", - config=Config(s3={"addressing_style": "path"}), + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) # Upload a file @@ -118,6 +105,8 @@ The examples below use `eu-west-1`, the default region. For a bucket in `us-east + Save this as `upload.mjs` (it uses ES modules and top-level `await`), then run `node upload.mjs`: + ```javascript import { S3Client, PutObjectCommand, ListObjectsV2Command } from "@aws-sdk/client-s3"; import { readFileSync } from "fs"; @@ -126,6 +115,9 @@ The examples below use `eu-west-1`, the default region. For a bucket in `us-east endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", forcePathStyle: true, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", credentials: { accessKeyId: "YOUR_ACCESS_KEY", secretAccessKey: "YOUR_SECRET_KEY", diff --git a/docs/quickstart/sdk.mdx b/docs/quickstart/sdk.mdx index bf47cf4..3c376f2 100644 --- a/docs/quickstart/sdk.mdx +++ b/docs/quickstart/sdk.mdx @@ -13,6 +13,15 @@ Choose your language and follow along. Each example uploads a file and verifies These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and region `us-east-1`. The endpoint, the region, and your access key must all refer to the same region. ::: +Each example reads your key from the standard AWS environment variables, the same names the console's **Download .env** writes. Set them in your shell before you run an example, and keep the secret out of your code: + +```bash +export AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY +export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY +``` + +The Python and JavaScript examples upload `my-file.txt`, so create it first: `echo "hello" > my-file.txt`. + ```bash @@ -26,17 +35,16 @@ These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, s3 = boto3.client( "s3", endpoint_url="https://s3.eu-west-1.filonecontent.com", - aws_access_key_id="YOUR_ACCESS_KEY", - aws_secret_access_key="YOUR_SECRET_KEY", region_name="eu-west-1", - config=Config(s3={"addressing_style": "path"}), + # Credentials come from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) # Upload a file (create the bucket first in the dashboard) - s3.upload_file("my-file.txt", "my-sdk-bucket", "my-file.txt") + s3.upload_file("my-file.txt", "my-bucket", "my-file.txt") # Verify - response = s3.list_objects_v2(Bucket="my-sdk-bucket") + response = s3.list_objects_v2(Bucket="my-bucket") for obj in response.get("Contents", []): print(f"{obj['Key']} ({obj['Size']} bytes)") ``` @@ -47,6 +55,8 @@ These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, npm install @aws-sdk/client-s3 ``` + Save this as `upload.mjs` (it uses ES modules and top-level `await`), then run `node upload.mjs`: + ```javascript import { S3Client, PutObjectCommand, ListObjectsV2Command } from "@aws-sdk/client-s3"; import { readFileSync } from "fs"; @@ -55,22 +65,22 @@ These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", forcePathStyle: true, - credentials: { - accessKeyId: "YOUR_ACCESS_KEY", - secretAccessKey: "YOUR_SECRET_KEY", - }, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", + // Credentials come from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY }); // Upload a file (create the bucket first in the dashboard) await client.send(new PutObjectCommand({ - Bucket: "my-sdk-bucket", + Bucket: "my-bucket", Key: "my-file.txt", Body: readFileSync("my-file.txt"), })); // Verify const { Contents } = await client.send( - new ListObjectsV2Command({ Bucket: "my-sdk-bucket" }) + new ListObjectsV2Command({ Bucket: "my-bucket" }) ); Contents?.forEach((obj) => console.log(obj.Key, obj.Size)); ``` @@ -78,16 +88,21 @@ These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, ```bash + mkdir filone-quickstart && cd filone-quickstart + go mod init example.com/filone-quickstart go get github.com/aws/aws-sdk-go-v2/service/s3 go get github.com/aws/aws-sdk-go-v2/credentials ``` + Save this as `main.go` and run `go run .`: + ```go package main import ( "context" "fmt" + "log" "os" "strings" @@ -102,8 +117,8 @@ These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, Region: "eu-west-1", UsePathStyle: true, Credentials: credentials.NewStaticCredentialsProvider( - os.Getenv("FIL_ACCESS_KEY"), - os.Getenv("FIL_SECRET_KEY"), + os.Getenv("AWS_ACCESS_KEY_ID"), + os.Getenv("AWS_SECRET_ACCESS_KEY"), "", ), }) @@ -111,16 +126,22 @@ These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, ctx := context.Background() // Upload (create the bucket first in the dashboard) - client.PutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String("my-sdk-bucket"), + _, err := client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String("my-bucket"), Key: aws.String("hello.txt"), Body: strings.NewReader("Hello from Go!"), }) + if err != nil { + log.Fatal(err) + } // List - out, _ := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{ - Bucket: aws.String("my-sdk-bucket"), + out, err := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{ + Bucket: aws.String("my-bucket"), }) + if err != nil { + log.Fatal(err) + } for _, obj := range out.Contents { fmt.Printf("%s (%d bytes)\n", *obj.Key, *obj.Size) } @@ -132,7 +153,7 @@ These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, For more detailed examples including multipart uploads and presigned URLs, see the dedicated SDK pages: diff --git a/docs/reference/errors.mdx b/docs/reference/errors.mdx index 2c815a3..4aa2770 100644 --- a/docs/reference/errors.mdx +++ b/docs/reference/errors.mdx @@ -66,3 +66,13 @@ These come from the Fil One console at [app.filone.com](https://app.filone.com), **`AccessDenied` (403)** -- Not always a permissions problem. In `eu-west-1` this is also what an unimplemented operation returns, and what you get instead of a 404 for a bucket or key you cannot see. Confirm the operation is supported in your region in the [compatibility matrix](/reference/s3-compatibility) before auditing your access-key scopes. **`ServiceUnavailable` (503)** -- Transient. Retry with exponential backoff. If persistent, check [status.filone.com](https://status.filone.com). + +### First-request problems + +| Symptom | Likely cause | Fix | +|---------|--------------|-----| +| `InvalidAccessKeyId`, `SignatureDoesNotMatch` or 403 on every request, with a key you just created | The key, the endpoint and the region setting don't all refer to the same region | Use the endpoint and region of the key's region. A key created for `us-east-1` is rejected by `s3.eu-west-1.filonecontent.com`, and the other way round. | +| DNS lookup failure or a connection error for a host like `my-bucket.s3.eu-west-1.filonecontent.com` | The client is using virtual-hosted-style addressing | Enable path-style addressing in your client. See [SDKs & Tools](/sdk/overview#connection-details). | +| `AccessDenied` when deleting an object, although uploads work | The key doesn't have the **Delete** permission. It isn't pre-selected when you create a key | Create a key with **Delete**, or rotate this one with it added. See [API Keys](/security/api-keys#key-permissions). | +| `BadDigest` when a browser uploads to a presigned URL made with the AWS SDK for JavaScript | SDK v3.729 and later sign a checksum computed when the URL is made, which the real upload doesn't match | Set `requestChecksumCalculation: "WHEN_REQUIRED"` on the `S3Client` that creates the URL. See [JavaScript](/sdk/javascript#presigned-urls). | +| `list-multipart-uploads` or `abort-multipart-upload` fails with 403 in `us-east-1` | Keys created there before 26 August 2026 don't carry these multipart actions, and existing keys can't be updated | Create a new key. See [Cleaning up incomplete uploads](/storage/multipart-uploads#cleaning-up-incomplete-uploads). | diff --git a/docs/reference/overview.mdx b/docs/reference/overview.mdx index 485d8b6..32461fe 100644 --- a/docs/reference/overview.mdx +++ b/docs/reference/overview.mdx @@ -18,7 +18,7 @@ All requests must use HTTPS and authenticate with AWS Signature Version 4 (SigV4 Fil One accepts standard S3 API requests. Use path-style addressing: -``` +```text # Path style https://s3.eu-west-1.filonecontent.com/my-bucket/my-key ``` diff --git a/docs/reference/s3-compatibility.mdx b/docs/reference/s3-compatibility.mdx index 704021c..cdd4c58 100644 --- a/docs/reference/s3-compatibility.mdx +++ b/docs/reference/s3-compatibility.mdx @@ -3,7 +3,7 @@ title: S3 Compatibility description: Supported S3 operations, authentication, and endpoint configuration. --- -Fil One provides an S3-compatible API. If your application works with AWS S3, it works with Fil One — point your SDK or CLI at our endpoint and authenticate with your API keys. +Fil One provides an S3-compatible API. It works with standard S3 SDKs and tools once you set the endpoint and enable path-style addressing; see the gaps below. Authenticate with your [API keys](/security/api-keys). ## Endpoint @@ -37,7 +37,7 @@ Specific size and count limits quoted in this table (5 TB max object, 5 GB singl :::warning How unsupported operations respond in `eu-west-1` In `eu-west-1`, operations that Fil One does not implement return **`AccessDenied` (HTTP 403)**, not `NotImplemented` (501). This is confirmed by a compatibility test run against the region. -A 403 from `PutBucketVersioning`, `PutBucketPolicy`, `PutBucketAcl`, `PutBucketEncryption`, `PutBucketLifecycleConfiguration`, or the tagging operations means *the feature is absent*, not that your key lacks a permission. Don't spend time auditing your access-key scopes for these. Code that branches on `NotImplemented` to degrade gracefully needs to treat 403 on these operations the same way. +A 403 from `PutBucketPolicy`, `PutBucketAcl`, `PutBucketLifecycleConfiguration`, or the tagging operations means *the feature is absent*, not that your key lacks a permission. Bucket-configuration calls such as `PutBucketVersioning` and `PutBucketEncryption` can't be granted to any key, so they fail the same way. Don't spend time auditing your access-key scopes for these. Code that branches on `NotImplemented` to degrade gracefully needs to treat 403 on these operations the same way. ::: ### Bucket operations @@ -49,11 +49,11 @@ A 403 from `PutBucketVersioning`, `PutBucketPolicy`, `PutBucketAcl`, `PutBucketE | `ListBuckets` | ✅ Supported | | | `HeadBucket` | ✅ Supported | | | `GetBucketVersioning` | ✅ Supported | Returns `Enabled` for versioned buckets, `Suspended` is never returned. | -| `PutBucketVersioning` | ⚠️ Region-dependent | Rejected with `AccessDenied` in `eu-west-1`, for enable as well as suspend requests: versioning there is set at bucket creation and cannot be changed over the API at all. In `us-east-1`, accepted for SDK compatibility, but versioning still cannot be suspended once enabled. | +| `PutBucketVersioning` | ❌ Not available to access keys | No access key can be granted this action, in either region. Versioning is set when you create the bucket in the console and cannot be changed afterwards. | | `GetBucketObjectLockConfiguration` | ✅ Supported | Returns the bucket-level default retention policy, if set. | -| `PutBucketObjectLockConfiguration` | ✅ Supported | Sets the default retention policy in Governance or Compliance mode. | -| `GetBucketEncryption` | ⚠️ Region-dependent | Returns `AccessDenied` in `eu-west-1` rather than an encryption configuration. Supported in `us-east-1`. Encryption is always on regardless of what this call returns. | -| `PutBucketEncryption` | ⚠️ Region-dependent | Rejected with `AccessDenied` in `eu-west-1`, including a valid SSE-S3 default rule. In `us-east-1`, accepted for SDK compatibility but has no effect. Encryption cannot be modified or disabled in either region. | +| `PutBucketObjectLockConfiguration` | ❌ Not available to access keys | No access key can be granted this action, in either region. Object Lock and the default retention are set when you create the bucket in the console. | +| `GetBucketEncryption` | ❌ Not available to access keys | No access key can be granted this action, in either region. Encryption is always on. | +| `PutBucketEncryption` | ❌ Not available to access keys | No access key can be granted this action, in either region. Encryption cannot be modified or disabled. | | `DeleteBucketEncryption` | ❌ Not supported | Rejected with `AccessDenied` in `eu-west-1`. Encryption cannot be disabled. | | `GetBucketAcl` | ❌ Not supported | ACL model is not implemented. Returns `AccessDenied` in `eu-west-1`. See [ACLs](#acls). | | `PutBucketAcl` | ❌ Not supported | ACL model is not implemented. Rejected with `AccessDenied` in `eu-west-1`. | @@ -81,11 +81,11 @@ A 403 from `PutBucketVersioning`, `PutBucketPolicy`, `PutBucketAcl`, `PutBucketE | `HeadObject` | ✅ Supported | | | `ListObjectsV2` | ✅ Supported | | | `ListObjectVersions` | ✅ Supported | Returns all versions and delete markers. Supports `Prefix` and `KeyMarker` filters. | -| `CopyObject` | ⚠️ Region-dependent | Confirmed working in `us-east-1`, including copying a specific `VersionId` onto the current key. In `eu-west-1`, most copy operations pass a compatibility run, so plain server-side copy works there, but **copying a specific `VersionId` is still unverified** in that region because the test harness cannot configure versioning over the API. Verify a version-promote copy against your own bucket before relying on it. | +| `CopyObject` | ⚠️ Region-dependent | Confirmed working in `us-east-1`, including copying a specific `VersionId` onto the current key. In `eu-west-1`, most copy operations pass a compatibility run, so plain server-side copy works there, but **copying a specific `VersionId` is not yet confirmed** in that region. Verify a version-promote copy against your own bucket before relying on it. | | `GetObjectRetention` | ✅ Supported | Returns the Object Lock retention for a specific version. | -| `PutObjectRetention` | ✅ Supported | Set, extend, or (via S3's bypass-governance-retention mechanism) shorten a version's retention. Requires the matching access-key permission. | +| `PutObjectRetention` | ✅ Supported | Set or extend a version's retention. Retention can't be shortened, because no key can be granted the bypass-governance permission. Requires the **Set retention** permission (Owner-only to grant). | | `GetObjectLegalHold` | ✅ Supported | Requires the matching access-key permission. | -| `PutObjectLegalHold` | ✅ Supported | Blocks delete while a hold is active. Requires the matching access-key permission. | +| `PutObjectLegalHold` | ✅ Supported | Blocks delete while a hold is active. Requires the **Set legal hold** permission (Owner-only to grant). | | `GetObjectAttributes` | ❌ Not supported | Returns `AccessDenied` in `eu-west-1`. Use `HeadObject` for size, ETag, and metadata instead. | | `GetObjectAcl` | ❌ Not supported | ACL model is not implemented. Returns `AccessDenied` in `eu-west-1`, including on objects uploaded with a canned-ACL header. | | `PutObjectAcl` | ❌ Not supported | ACL model is not implemented. Rejected with `AccessDenied` in `eu-west-1`. | @@ -117,8 +117,8 @@ Versioning is **opt-in** and configured at bucket creation time. Once enabled on | `ListObjectVersions` | ✅ Supported | Lists all versions and delete markers in a bucket. | | `GetObject` with `VersionId` | ✅ Supported | Retrieves a specific historical version by ID. | | `DeleteObject` with `VersionId` | ✅ Supported | Permanently deletes a specific version, bypassing delete markers. | -| `PutBucketVersioning` (suspend) | ❌ Rejected | Versioning cannot be suspended once enabled. Suspend requests return an error. In `eu-west-1` that error is `AccessDenied`, and enable requests are rejected the same way. | -| `CopyObject` with `x-amz-copy-source-version-id` | ⚠️ Region-dependent | Confirmed working in `us-east-1` — copy a specific version onto the current key to promote it. Still unverified in `eu-west-1`: plain copy works there, but the version-id form could not be tested because versioning cannot be configured over the API in that region. | +| `PutBucketVersioning` | ❌ Not available to access keys | Versioning is set at bucket creation and cannot be suspended or changed. | +| `CopyObject` with `x-amz-copy-source-version-id` | ⚠️ Region-dependent | Confirmed working in `us-east-1` — copy a specific version onto the current key to promote it. Not yet confirmed in `eu-west-1`: plain copy works there, but the version-id form has not been tested. | The Fil One **dashboard** has no restore, roll-back, or "make current" action — you can list, download, and delete any prior version there, but not promote one to current. In `us-east-1`, you can promote an older version via the API with `CopyObject` (see above). In `eu-west-1`, plain server-side copy works but the version-id form is unverified, so test it against your own bucket first and fall back to downloading the version and uploading it again if it fails. @@ -129,24 +129,24 @@ See [Versioning](/storage/versioning) for detailed usage and examples. Object Lock enforces WORM (Write-Once-Read-Many) protection. Both Governance and Compliance mode are supported. Object Lock requires versioning, and both are set at bucket creation time. :::note Where the evidence comes from -Object Lock, retention, and Legal Hold work in **both** regions. `us-east-1` is covered by an automated compatibility suite (39/39 object-lock tests passing). `eu-west-1` was verified by engineering testing rather than by that suite: a compatibility run against the region could not exercise these operations, because the harness was unable to create an Object-Lock-enabled bucket to test against, which was a limitation of the test setup and not a product gap. +Object Lock, retention, and Legal Hold are verified in **both** regions: by an automated compatibility suite in `us-east-1`, and by engineering testing in `eu-west-1`. ::: | Operation | Status | Notes | |-----------|--------|-------| | `GetBucketObjectLockConfiguration` | ✅ Supported | Returns the bucket-level default retention policy. | -| `PutBucketObjectLockConfiguration` | ✅ Supported | Sets the default retention (Governance or Compliance mode, 1 day – 100 years). | +| `PutBucketObjectLockConfiguration` | ❌ Not available to access keys | The default retention (Governance or Compliance, 1 day – 100 years) is set when you create the bucket in the console. | | `GetObjectRetention` | ✅ Supported | Returns the retention setting for a specific object version. | -| `PutObjectRetention` | ✅ Supported | Extend a retention period, or shorten one via S3's bypass-governance-retention mechanism (correctly rejected without it). Requires the matching access-key permission. | +| `PutObjectRetention` | ✅ Supported | Set or extend a retention period. It can't be shortened: no key can be granted the bypass-governance permission. Requires the **Set retention** permission (Owner-only to grant). | | `GetObjectLegalHold` | ✅ Supported | Requires the matching access-key permission. | -| `PutObjectLegalHold` | ✅ Supported | Blocks delete while a hold is active. Requires the matching access-key permission. | +| `PutObjectLegalHold` | ✅ Supported | Blocks delete while a hold is active. Requires the **Set legal hold** permission (Owner-only to grant). | **Object Lock modes:** | Mode | Status | |------|--------| | Governance | ✅ Supported — the default when you enable Object Lock. In standard S3, Governance retention can be overridden by a caller with the bypass permission, but **Fil One does not currently expose a grantable bypass permission**, so treat Governance objects as protected for their retention period in practice. | -| Compliance | ✅ Supported — no user, including the account owner, can delete a locked object or shorten its retention. | +| Compliance | ✅ Supported — no user, including the organization Owner, can delete a locked object or shorten its retention. | See [Object Lock](/storage/object-lock) for compliance use cases, retention configuration, and examples. @@ -155,7 +155,7 @@ See [Object Lock](/storage/object-lock) for compliance use cases, retention conf | Operation | Status | Notes | |-----------|--------|-------| | Presigned `GetObject` | ✅ Supported | Generate time-limited download URLs without requiring API credentials. | -| Presigned `PutObject` | ✅ Supported | Generate time-limited upload URLs for direct client or browser uploads. | +| Presigned `PutObject` | ✅ Supported | Generate time-limited upload URLs for direct client or browser uploads. With the AWS SDK for JavaScript v3.729 or later, set `requestChecksumCalculation: "WHEN_REQUIRED"` on the client, or the upload fails with `BadDigest`. See [JavaScript](/sdk/javascript#presigned-urls). | ### Server-side encryption @@ -165,11 +165,10 @@ Encryption is **always enabled** on every Fil One bucket. There is nothing to co |---------|--------|-------| | Server-side encryption at rest | ✅ Always on | Applied automatically by the regional storage gateway — no headers required, and it cannot be disabled. | | Encryption in transit (TLS) | ✅ Always on | All API connections use HTTPS. HTTP is rejected. | -| `GetBucketEncryption` | ⚠️ Region-dependent | Supported in `us-east-1`. Returns `AccessDenied` in `eu-west-1`, so you cannot read back a configuration there. Encryption is on either way. | -| `PutBucketEncryption` | ⚠️ Region-dependent | Rejected with `AccessDenied` in `eu-west-1`, even for a valid SSE-S3 rule. Accepted but ineffective in `us-east-1`. Encryption cannot be modified or disabled. | -| SSE-S3 (`AES256`) | ⚠️ Region-dependent | Accepted in `us-east-1`. In `eu-west-1` the bucket-level SSE-S3 configuration operations are rejected with `AccessDenied`. Encryption is applied automatically in both regions, so no header is needed. | +| `GetBucketEncryption` / `PutBucketEncryption` | ❌ Not available to access keys | No access key can be granted these actions, in either region. Encryption is on either way and cannot be modified or disabled. | +| SSE-S3 (`AES256`) header | Not needed | Encryption is applied automatically in both regions, so send no encryption header. | | SSE-KMS (`aws:kms`) | ❌ Not supported | Rejected in **both** regions: `InvalidRequest` in `us-east-1`, and `AccessDenied` or `InvalidRequest` in `eu-west-1` depending on the operation. Affects `PutObject`, `CopyObject`, and `CreateMultipartUpload`. Omit encryption headers, server-side encryption is applied automatically. | -| SSE-C (customer-provided keys) | ❌ Not supported | Keys are held by the regional storage operator. There is no customer-managed-key option. Requests carrying SSE-C headers are rejected in `eu-west-1`. | +| SSE-C (customer-provided keys) | ❌ Not supported | Keys are held by the regional storage operator. There is no customer-managed-key option. Requests carrying SSE-C headers are rejected in `eu-west-1`; not yet confirmed in `us-east-1`. Don't send them. | | Client-side encryption | ✅ Optional | Encrypt data in your own application before upload. AWS's S3 Encryption Client exists only for some SDKs (Java, .NET, Go, Ruby) — not boto3, the CLI, or JS v3 — so with those you supply your own crypto. Server-side encryption is still applied on top. | See [Encryption](/security/encryption) for details. @@ -193,11 +192,11 @@ To limit what a key can reach, scope it to specific buckets when you create it. | Feature | Timeline | Notes | |---------|----------|-------| -| Lifecycle rules (expiration, transitions) | Phase 2 | Planned. Affects archival and cleanup workflows. | -| Event notifications (SNS/SQS/Lambda triggers) | Phase 2 | Planned. | -| Object and bucket tagging | Phase 2 | Planned. | -| Additional regions | Phase 2 | `eu-west-1` and `us-east-1` are available today. | -| IAM users, roles, and bucket policies on the S3 API | Not yet supported | The S3 API has no IAM users, roles, or bucket policies. Access is controlled by each access key's permissions and bucket scope. Team members and roles exist in the console, in beta: see [Organization](/app/organization#roles-and-permissions). | +| Lifecycle rules (expiration, transitions) | Planned | Affects archival and cleanup workflows. | +| Event notifications (SNS/SQS/Lambda triggers) | Planned | | +| Object and bucket tagging | Planned | | +| Additional regions | Planned | `eu-west-1` and `us-east-1` are available today. | +| IAM users, roles, and bucket policies on the S3 API | Not yet supported | The S3 API has no IAM users, roles, or bucket policies. Access is controlled by each access key's permissions and bucket scope. Team members and roles exist in the console: see [Organization](/app/organization#roles-and-permissions). | | S3 Select | Not planned | | | S3 Inventory | Not planned | | | S3 Batch Operations | Not planned | | @@ -239,7 +238,7 @@ Some invalid requests are also **accepted** where AWS rejects them (HTTP 200 or ## Known behavioral issues in `eu-west-1` -These are confirmed deviations that can affect a correctly written S3 client. They are open engineering issues, not intended behavior. +These are confirmed deviations that can affect a correctly written S3 client. They are known issues, not intended behavior. | Area | Issue | Workaround | |------|-------|------------| @@ -257,7 +256,7 @@ Fil One is S3-compatible, not an S3 clone. A few behaviors differ: | Server-side copy | `CopyObject` supported. | Confirmed working in `us-east-1`. In `eu-west-1` plain copy works, but the version-id form (promoting an old version) is unverified. | | Encryption | Optional and configurable. Off by default for older buckets. | Always on. Cannot be disabled. Keys are held by the regional storage operator; no customer-managed keys. | | Bucket management | `CreateBucket` and `DeleteBucket` supported via API. Requires an empty bucket to delete. | Region-dependent. Supported via API in `us-east-1`; in `eu-west-1` buckets are managed through the dashboard only. | -| IAM and policies | Full IAM with users, roles, and bucket policies. | No IAM users, roles, or bucket policies on the S3 API. Access is controlled by each access key's permissions and bucket scope. The console has organizations with member roles, in beta: see [Organization](/app/organization#roles-and-permissions). | +| IAM and policies | Full IAM with users, roles, and bucket policies. | No IAM users, roles, or bucket policies on the S3 API. Access is controlled by each access key's permissions and bucket scope. The console has organizations with member roles: see [Organization](/app/organization#roles-and-permissions). | | Public access | Configurable via ACLs and bucket policies. | No public access. All requests require authentication. Canned-ACL headers on uploads are ignored rather than rejected, and never make an object public. | | Error codes for missing features | `NotImplemented` (501). | `AccessDenied` (403) in `eu-west-1`. A 403 on a bucket-configuration call means the feature is absent, not that your key lacks permission. | | Lifecycle rules | Supported (expiration, storage class transitions). | Not supported. Planned for a future release. | diff --git a/docs/sdk/cli.mdx b/docs/sdk/cli.mdx index e2d03bd..1e5ea31 100644 --- a/docs/sdk/cli.mdx +++ b/docs/sdk/cli.mdx @@ -11,7 +11,7 @@ Examples here use `eu-west-1`, the default region. For a bucket in `us-east-1`, ## Installation -Use **AWS CLI v2**. Version 1 (`pip install awscli`) does not read `endpoint_url` from `~/.aws/config`, so the profile setup below silently won't work — install v2 instead: +Use **AWS CLI v2**, version 2.13 or later, so the CLI reads `endpoint_url` from your profile. `pip install awscli` installs v1; install v2 instead: ```bash brew install awscli @@ -86,17 +86,18 @@ aws s3 ls --endpoint-url https://s3.eu-west-1.filonecontent.com ### Create a bucket -`CreateBucket` is region-dependent. It is not available in `eu-west-1` — use the [Fil One dashboard](https://app.filone.com) there, via **Buckets → Create bucket**. In `us-east-1`, with a key that has the `CreateBucket` permission: +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a `us-east-1` profile (here `filone-us`, set up like `filone` above but with the `us-east-1` endpoint, region and key) whose key has the `CreateBucket` permission: ```bash -aws s3 mb s3://my-bucket --profile filone +aws s3 mb s3://my-bucket --profile filone-us ``` -Note that versioning and Object Lock can only be set when the bucket is created, and only from the dashboard. See [Buckets](/storage/buckets). +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](/storage/buckets). ### Upload a file ```bash +# report.pdf is any local file aws s3 cp report.pdf s3://my-bucket/reports/report.pdf --profile filone ``` @@ -134,10 +135,10 @@ aws s3 rm s3://my-bucket/reports/report.pdf --profile filone ### Delete a bucket -`DeleteBucket` support depends on the region. In `us-east-1` you can remove an empty bucket with a key that has the `DeleteBucket` permission: +`DeleteBucket` support depends on the region. In `us-east-1` you can remove an empty bucket with a `us-east-1` profile whose key has the `DeleteBucket` permission: ```bash -aws s3 rb s3://my-bucket --profile filone +aws s3 rb s3://my-bucket --profile filone-us ``` In `eu-west-1` the operation is not available over the S3 API. Delete the bucket from the [Fil One dashboard](https://app.filone.com) instead, via the bucket's actions menu in **Buckets** (Owner and Admin roles only). See [Buckets](/storage/buckets#deleting-a-bucket). diff --git a/docs/sdk/go.mdx b/docs/sdk/go.mdx index d21de01..866a42e 100644 --- a/docs/sdk/go.mdx +++ b/docs/sdk/go.mdx @@ -11,11 +11,13 @@ Examples here use `eu-west-1`, the default region. For a bucket in `us-east-1`, ## Installation +In a new directory, create a module and add the SDK: + ```bash +go mod init example.com/filone go get github.com/aws/aws-sdk-go-v2/aws go get github.com/aws/aws-sdk-go-v2/credentials go get github.com/aws/aws-sdk-go-v2/service/s3 -go get github.com/aws/aws-sdk-go-v2/service/s3/types ``` ## Client configuration @@ -36,8 +38,8 @@ func newClient() *s3.Client { BaseEndpoint: aws.String("https://s3.eu-west-1.filonecontent.com"), Region: "eu-west-1", Credentials: credentials.NewStaticCredentialsProvider( - os.Getenv("FIL_ACCESS_KEY"), - os.Getenv("FIL_SECRET_KEY"), + os.Getenv("AWS_ACCESS_KEY_ID"), + os.Getenv("AWS_SECRET_ACCESS_KEY"), "", ), UsePathStyle: true, @@ -45,23 +47,27 @@ func newClient() *s3.Client { } ``` -Set `FIL_ACCESS_KEY` and `FIL_SECRET_KEY` as environment variables. Never hardcode credentials in source code. +Set `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` as environment variables, the names the console's **Download .env** writes. Never hardcode credentials in source code. -The operation snippets below are fragments: each assumes the `client` returned by `newClient()` above and a `ctx` (e.g. `ctx := context.TODO()`) in scope, and shows only the imports specific to that snippet. +The operation snippets below are fragments: each assumes the `client` returned by `newClient()` above, a `ctx` (e.g. `ctx := context.TODO()`), and `"log"` imported, and shows only the other imports specific to that snippet. ## Core operations ### Create a bucket -`CreateBucket` is region-dependent. It is not available in `eu-west-1` — use the [Fil One dashboard](https://app.filone.com) there, via **Buckets → Create bucket**. In `us-east-1`, with a key that has the `CreateBucket` permission: +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a client built with the `us-east-1` endpoint and region, and a `us-east-1` key that has the `CreateBucket` permission: ```go -_, err := client.CreateBucket(ctx, &s3.CreateBucketInput{ +// usClient: like newClient(), with BaseEndpoint https://s3.us-east-1.filonecontent.com and Region "us-east-1" +_, err := usClient.CreateBucket(ctx, &s3.CreateBucketInput{ Bucket: aws.String("my-bucket"), }) +if err != nil { + log.Fatal(err) +} ``` -Note that versioning and Object Lock can only be set when the bucket is created, and only from the dashboard. See [Buckets](/storage/buckets). +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](/storage/buckets). ### Upload an object @@ -78,9 +84,15 @@ _, err := client.PutObject(ctx, &s3.PutObjectInput{ Body: bytes.NewReader([]byte(`{"key":"value"}`)), ContentType: aws.String("application/json"), }) +if err != nil { + log.Fatal(err) +} -// Upload a file -f, _ := os.Open("report.pdf") +// Upload a local file (report.pdf must exist) +f, err := os.Open("report.pdf") +if err != nil { + log.Fatal(err) +} defer f.Close() _, err = client.PutObject(ctx, &s3.PutObjectInput{ @@ -89,6 +101,9 @@ _, err = client.PutObject(ctx, &s3.PutObjectInput{ Body: f, ContentType: aws.String("application/pdf"), }) +if err != nil { + log.Fatal(err) +} ``` ### Download an object @@ -104,13 +119,18 @@ result, err := client.GetObject(ctx, &s3.GetObjectInput{ Key: aws.String("reports/report.pdf"), }) if err != nil { - // handle error + log.Fatal(err) } defer result.Body.Close() -out, _ := os.Create("local-report.pdf") +out, err := os.Create("local-report.pdf") +if err != nil { + log.Fatal(err) +} defer out.Close() -io.Copy(out, result.Body) +if _, err := io.Copy(out, result.Body); err != nil { + log.Fatal(err) +} ``` ### List objects @@ -125,7 +145,7 @@ paginator := s3.NewListObjectsV2Paginator(client, &s3.ListObjectsV2Input{ for paginator.HasMorePages() { page, err := paginator.NextPage(ctx) if err != nil { - // handle error + log.Fatal(err) } for _, obj := range page.Contents { // obj.Size is a *int64; dereference it with aws.ToInt64 to print the number @@ -141,12 +161,16 @@ _, err := client.DeleteObject(ctx, &s3.DeleteObjectInput{ Bucket: aws.String("my-bucket"), Key: aws.String("reports/report.pdf"), }) +if err != nil { + log.Fatal(err) +} ``` ## Presigned URLs ```go import ( + "fmt" "time" "github.com/aws/aws-sdk-go-v2/service/s3" @@ -159,12 +183,20 @@ downloadReq, err := presigner.PresignGetObject(ctx, &s3.GetObjectInput{ Bucket: aws.String("my-bucket"), Key: aws.String("reports/report.pdf"), }, s3.WithPresignExpires(time.Hour)) +if err != nil { + log.Fatal(err) +} +fmt.Println(downloadReq.URL) // Upload URL valid for 15 minutes uploadReq, err := presigner.PresignPutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String("my-bucket"), Key: aws.String("uploads/new-file.txt"), }, s3.WithPresignExpires(15*time.Minute)) +if err != nil { + log.Fatal(err) +} +fmt.Println(uploadReq.URL) ``` ## Error handling @@ -172,6 +204,8 @@ uploadReq, err := presigner.PresignPutObject(ctx, &s3.PutObjectInput{ ```go import ( "errors" + "fmt" + "github.com/aws/smithy-go" ) diff --git a/docs/sdk/javascript.mdx b/docs/sdk/javascript.mdx index 2662281..b5d86ed 100644 --- a/docs/sdk/javascript.mdx +++ b/docs/sdk/javascript.mdx @@ -23,29 +23,40 @@ import { S3Client } from "@aws-sdk/client-s3"; const s3 = new S3Client({ endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", - credentials: { - accessKeyId: process.env.FIL_ACCESS_KEY, - secretAccessKey: process.env.FIL_SECRET_KEY, - }, forcePathStyle: true, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", }); ``` -Set `FIL_ACCESS_KEY` and `FIL_SECRET_KEY` as environment variables. Never hardcode credentials in source code. +The SDK reads your key from the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables, the names the console's **Download .env** writes. Never hardcode credentials in source code. + +The examples use ES modules and top-level `await`: save them as `.mjs` files, or run `npm pkg set type=module` in your project. + +:::warning Set the checksum options +Since v3.729, the SDK adds a CRC32 checksum to requests by default. On a presigned upload URL, that checksum is computed when the URL is made, so the real upload doesn't match it and Fil One rejects it with `BadDigest`. `requestChecksumCalculation: "WHEN_REQUIRED"` restores the earlier behavior. Fil One's own console sets the same options. +::: ## Core operations ### Create a bucket -`CreateBucket` is region-dependent. It is not available in `eu-west-1` — use the [Fil One dashboard](https://app.filone.com) there, via **Buckets → Create bucket**. In `us-east-1`, with a key that has the `CreateBucket` permission: +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a `us-east-1` client and a `us-east-1` key that has the `CreateBucket` permission: ```javascript -import { CreateBucketCommand } from "@aws-sdk/client-s3"; +import { S3Client, CreateBucketCommand } from "@aws-sdk/client-s3"; + +const s3Us = new S3Client({ + endpoint: "https://s3.us-east-1.filonecontent.com", + region: "us-east-1", + forcePathStyle: true, +}); -await s3.send(new CreateBucketCommand({ Bucket: "my-bucket" })); +await s3Us.send(new CreateBucketCommand({ Bucket: "my-bucket" })); ``` -Note that versioning and Object Lock can only be set when the bucket is created, and only from the dashboard. See [Buckets](/storage/buckets). +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](/storage/buckets). ### Upload an object @@ -61,7 +72,7 @@ await s3.send(new PutObjectCommand({ ContentType: "application/json", })); -// Upload a file +// Upload a local file (report.pdf must exist) await s3.send(new PutObjectCommand({ Bucket: "my-bucket", Key: "reports/report.pdf", @@ -142,7 +153,7 @@ const uploadUrl = await getSignedUrl( ## Error handling ```javascript -import { S3ServiceException } from "@aws-sdk/client-s3"; +import { GetObjectCommand, S3ServiceException } from "@aws-sdk/client-s3"; try { await s3.send(new GetObjectCommand({ Bucket: "my-bucket", Key: "missing.txt" })); diff --git a/docs/sdk/overview.mdx b/docs/sdk/overview.mdx index 1549a1c..2ffe5f8 100644 --- a/docs/sdk/overview.mdx +++ b/docs/sdk/overview.mdx @@ -9,7 +9,7 @@ Fil One works with any tool or library that supports the S3 API. You do not need | Tool | Language / Platform | Install | |------|-------------------|---------| -| AWS CLI (v2) | Command line | `brew install awscli` (v2 required — v1 ignores `endpoint_url` in config) | +| AWS CLI (v2) | Command line | `brew install awscli` (v2.13 or later, which reads `endpoint_url` from a profile) | | boto3 | Python | `pip install boto3` | | AWS SDK v3 | JavaScript / TypeScript | `npm install @aws-sdk/client-s3` | | aws-sdk-go-v2 | Go | `go get github.com/aws/aws-sdk-go-v2/service/s3` | @@ -24,7 +24,7 @@ Every SDK and tool needs the same four things: |-----------|-------| | Endpoint | `https://s3..filonecontent.com` | | Region | `eu-west-1` or `us-east-1` | -| Credentials | Your Access Key ID and Secret Access Key from the dashboard | +| Credentials | Your Access Key ID and Secret Access Key, from **API Keys** in the console | | Path-style addressing | **Required.** Fil One does not support virtual-hosted-style URLs — enable path-style in every client (`forcePathStyle`, `addressing_style = path`, `UsePathStyle`, etc.) | The endpoint is region-specific, and it has to match the region of the bucket you are addressing: @@ -52,6 +52,6 @@ Most S3-compatible tools work with Fil One, subject to the same constraints as a - **rclone** -- Sync files between local storage and Fil One. Configure with `rclone config` using the S3 provider type. - **Cyberduck** -- GUI file browser for macOS and Windows. Add a new S3 connection with the Fil One endpoint. - **s3cmd** -- Command-line tool. Configure with `s3cmd --configure`, then set both `host_base = s3.eu-west-1.filonecontent.com` and `host_bucket = s3.eu-west-1.filonecontent.com/%(bucket)s` in `~/.s3cfg`. The `host_bucket` line is what forces path-style addressing; without it s3cmd stays in virtual-hosted mode and requests fail. -- **MinIO Client (mc)** -- `mc alias set filone https://s3.eu-west-1.filonecontent.com YOUR_KEY YOUR_SECRET`. Passing the secret on the command line leaves it in your shell history and the process list — prefer `mc alias set filone https://s3.eu-west-1.filonecontent.com` and let `mc` prompt for the key and secret interactively. +- **MinIO Client (mc)** -- `mc alias set filone https://s3.eu-west-1.filonecontent.com YOUR_ACCESS_KEY YOUR_SECRET_KEY`. Passing the secret on the command line leaves it in your shell history and the process list — prefer `mc alias set filone https://s3.eu-west-1.filonecontent.com` and let `mc` prompt for the key and secret interactively. -If you use a tool not listed here and run into compatibility issues, contact support. +If you use a tool not listed here and run into compatibility issues, [contact support](/app/support). diff --git a/docs/sdk/python.mdx b/docs/sdk/python.mdx index 9b0542d..dd779a7 100644 --- a/docs/sdk/python.mdx +++ b/docs/sdk/python.mdx @@ -19,41 +19,46 @@ pip install boto3 ```python import boto3 -import os from botocore.config import Config s3 = boto3.client( "s3", endpoint_url="https://s3.eu-west-1.filonecontent.com", - aws_access_key_id=os.environ["FIL_ACCESS_KEY"], - aws_secret_access_key=os.environ["FIL_SECRET_KEY"], region_name="eu-west-1", - config=Config(s3={"addressing_style": "path"}), + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) ``` -Set `FIL_ACCESS_KEY` and `FIL_SECRET_KEY` as environment variables. Never hardcode credentials in source code. +boto3 reads your key from the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables, the names the console's **Download .env** writes. Never hardcode credentials in source code. + +`signature_version="s3v4"` makes presigned URLs use SigV4. Without it, boto3 can sign presigned URLs with the older SigV2 scheme when you set a custom endpoint. :::warning Path-style addressing is required -Fil One only supports **path-style** URLs (`https://s3.eu-west-1.filonecontent.com/my-bucket/key`). boto3 defaults to virtual-hosted style (`https://my-bucket.s3.eu-west-1.filonecontent.com/key`) even with a custom `endpoint_url`, which fails with a DNS or 404-shaped error. The `config=Config(s3={"addressing_style": "path"})` line above is not optional — without it, every request fails. `region_name` is also required, since SigV4 cannot sign without a region. +Fil One only supports **path-style** URLs (`https://s3.eu-west-1.filonecontent.com/my-bucket/key`). boto3 defaults to virtual-hosted style (`https://my-bucket.s3.eu-west-1.filonecontent.com/key`) even with a custom `endpoint_url`, which fails with a DNS or 404-shaped error. Keep the `s3={"addressing_style": "path"}` setting above. `region_name` is also required, since SigV4 cannot sign without a region. ::: ## Core operations ### Create a bucket -`CreateBucket` is region-dependent. It is not available in `eu-west-1` — use the [Fil One dashboard](https://app.filone.com) there, via **Buckets → Create bucket**. In `us-east-1`, with a key that has the `CreateBucket` permission: +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a `us-east-1` client and a `us-east-1` key that has the `CreateBucket` permission: ```python -s3.create_bucket(Bucket="my-bucket") +s3_us = boto3.client( + "s3", + endpoint_url="https://s3.us-east-1.filonecontent.com", + region_name="us-east-1", + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), +) +s3_us.create_bucket(Bucket="my-bucket") ``` -Note that versioning and Object Lock can only be set when the bucket is created, and only from the dashboard. See [Buckets](/storage/buckets). +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](/storage/buckets). ### Upload an object ```python -# Upload from file path +# Upload from a local file path (report.pdf must exist) s3.upload_file("report.pdf", "my-bucket", "reports/report.pdf") # Upload with content type diff --git a/docs/security/account-security.mdx b/docs/security/account-security.mdx index 5966979..74b3d03 100644 --- a/docs/security/account-security.mdx +++ b/docs/security/account-security.mdx @@ -46,6 +46,8 @@ A recovery code is a single-use code for signing in if you lose access to your a Generating a new code invalidates the previous one, so store the new value somewhere durable before you close the dialog. +Signing in with a recovery code assumes you've lost your device, so the same sign-in asks you to set up a new two-factor method before you reach the console. Have an authenticator app or a passkey ready. + ## Changes to security settings require re-authentication Four actions require a session that was signed in with two-factor authentication or a passkey, even inside an already signed-in session: diff --git a/docs/security/api-keys.mdx b/docs/security/api-keys.mdx index efea56e..5995e83 100644 --- a/docs/security/api-keys.mdx +++ b/docs/security/api-keys.mdx @@ -10,14 +10,14 @@ API keys authenticate your requests to the Fil One S3 API. Each key consists of ## Creating an API key -1. Go to **API Keys** in the left menu of the dashboard. +1. Go to **API Keys** in the left sidebar of the console. 2. Click **Create new key** (this opens a dedicated page). 3. Give the key a descriptive name (e.g., `production-backend`, `ci-pipeline`). Names are limited to 64 characters (letters, numbers, spaces, and `_ - .`), and names starting with `filone-console` (in any capitalization) are reserved. 4. Choose the key's **region** (see [Region scope](#region-scope)). It is pre-set to `eu-west-1`, and it is fixed for the life of the key. -5. Set the key's permissions and bucket scope (see below). At least one permission is required, and you can only grant permissions your role holds (see [Who can create and manage keys](#who-can-create-and-manage-keys)). +5. Set the key's permissions and bucket scope (see below). **Read**, **Write**, and **List** are pre-selected, along with the two bucket configuration reads. For a read-only key, untick **Write**. At least one permission is required, and you can only grant permissions your role holds (see [Who can create and manage keys](#who-can-create-and-manage-keys)). 6. Optionally set an expiration: **Never expires**, **30 days**, or a **Custom** date. 7. Click **Create API key**. -8. **Copy the Secret Access Key immediately.** It is shown only once. If you lose it, [rotate the key](#rotating-a-key) to get a new one. +8. **Copy the Secret Access Key immediately.** It is shown only once. If you lose it, [rotate the key](#rotating-a-key) to get a new one. If you use **Download .env** or **Download .csv**, the file holds the secret in plain text: move it into your secrets store or credential file, delete the download, and never commit it. ## Key permissions @@ -32,11 +32,11 @@ Each key can be granted a combination of the following object-level permissions: | **List** | `ListObjectsV2` / `ListBucket`, and listing in-progress multipart uploads (`ListBucketMultipartUploads`) | | **Delete** | `DeleteObject` | -You can grant any combination of these permissions. A key with only **Read** and **List** permissions is suitable for read-only access, such as a CDN or analytics pipeline. A key with **Write** but not **Delete** can upload new objects and overwrite existing ones, but cannot delete them. +You can grant any combination of these permissions. A key with only **Read** and **List** permissions is suitable for read-only access, such as a CDN or analytics pipeline. A key with **Write** but not **Delete** can upload new objects and overwrite existing ones, but cannot delete them. Overwriting replaces an object's data, so on a bucket without [versioning](/storage/versioning) a **Write** key can still destroy data. Use versioning or [Object Lock](/storage/object-lock) if that matters. The **Read** grant differs by region. In `us-east-1` it also includes `ListBucket`, so a key with **Read** but not **List** can still list object names there. In `eu-west-1`, **Read** does not include listing. -Listing the *names* of your buckets (`ListAllMyBuckets`) is granted to every key automatically and is not one of the permissions above. Note that the operator's documented **Write** grant covers `PutObject` and `AbortMultipartUpload`; the `CreateMultipartUpload` / `UploadPart` / `CompleteMultipartUpload` operations are not separately enumerated in the grant map. +Listing the *names* of your buckets (`ListAllMyBuckets`) is granted to every key automatically and is not one of the permissions above. Multipart uploads (`CreateMultipartUpload`, `UploadPart`, `CompleteMultipartUpload`) need **Write**. See [Multipart Uploads](/storage/multipart-uploads). ### Bucket management permissions @@ -92,7 +92,11 @@ A key can only carry permissions that your [role](/app/organization#roles-and-pe - **Members** can create keys, and see, rotate, and delete only the keys they created. - **Admins** and **Owners** can create keys and see, rotate, and delete every key in the organization. -Keys follow the person who created them. If a member's role is narrowed, any key they created that the new role couldn't create is revoked. Removing a member from the organization revokes the keys they created. +Keys follow the person who created them. + +:::warning Membership changes revoke keys +If a member's role is narrowed, any key they created that the new role couldn't create is revoked. Removing a member from the organization revokes every key they created, and so does transferring ownership for keys an Admin can't hold. The revoked keys stop working immediately, and the member is emailed a list of them. Before you change someone's access, move any application that uses their keys onto a new key. +::: ## Region scope @@ -102,7 +106,7 @@ The region also determines which permissions are available: the bucket managemen ## Bucket scope -By default, a key has access to all buckets in your account. You can restrict a key to one or more specific buckets, which limits **object operations** to that set. Note that listing your bucket *names* (`ListAllMyBuckets`) is always permitted, so bucket scoping restricts access to bucket **contents** rather than hiding that other buckets exist. +By default, a key has access to all buckets in the key's region. You can restrict a key to one or more specific buckets, which limits **object operations** to that set. Note that listing your bucket *names* (`ListAllMyBuckets`) is always permitted, so bucket scoping restricts access to bucket **contents** rather than hiding that other buckets exist. This is useful when: - Different services need access to different buckets @@ -111,7 +115,7 @@ This is useful when: ## Key expiration -You can set an expiration date when creating a key. After the expiration date, the key no longer authenticates and requests signed with it fail with a `403` (typically `AccessDenied` or `InvalidAccessKeyId`). +You can set an expiration date when creating a key. The key works through the whole of that day (UTC) and stops at the start of the next one. After that, the key no longer authenticates and requests signed with it fail with a `403` (typically `AccessDenied` or `InvalidAccessKeyId`). Expiring keys are useful for: - Temporary access grants @@ -120,19 +124,18 @@ Expiring keys are useful for: ## Viewing and managing keys -Go to **API Keys** in the left menu to see your keys. The list shows: +Go to **API Keys** in the left sidebar to see your keys. The list shows: | Column | Description | |--------|-------------| | Name | The label you gave the key at creation, with the Access Key ID shown beneath it | | Region | The region the key belongs to (hidden on narrow screens) | | Buckets | Which buckets the key can access (all, or a specific set) | -| Permissions | The permissions granted to the key | +| Permissions | The object permissions as badges, and a **+***n* badge for the rest | | Created by | Who created the key, and who rotated it and when. Shown when your organization has more than one member | -| Status | Currently always **Active** | -| Last Used | Currently always **Never** | +| Status | **Active**, or **Expired** once the expiry date has passed | -**Status** and **Last Used** are placeholders for now, and the list doesn't show a key's expiry date, so keep your own record of when each key expires. You cannot view the Secret Access Key after creation. +Click a key's row to see its expiry date, region, buckets, and full permissions. The console doesn't show when a key was last used, so name keys after what uses them. You cannot view the Secret Access Key after creation. See [API Keys in the console](/app/api-keys#the-key-list) for search, filters, and deleting several keys at once. ## Rotating a key @@ -150,7 +153,7 @@ To move an application onto a key with different permissions or buckets, create ## Revoking a key -Find the key in **API Keys**, open its **⋯** action menu, and choose **Delete**. Deletion is forwarded to the regional storage operator; the key stops working once that change propagates, so treat revocation as taking effect quickly rather than at a guaranteed instant, and rotate anything that depended on it. +Find the key in **API Keys**, open its **⋯** action menu, and choose **Delete**. A deleted key can't be restored. Anything that uses it loses access, so switch your applications to another key first. The key stays in your list until its revocation is confirmed. Treat revocation as taking effect quickly rather than at a guaranteed instant. ## Security best practices @@ -159,7 +162,8 @@ Find the key in **API Keys**, open its **⋯** action menu, and choose **Delete* - **Scope keys to specific buckets** when possible, especially for external integrations. - **Set expiration dates** on keys that are only needed temporarily. - **Rotate keys periodically.** Use **Rotate** on the key, then update your application with the new credentials. See [Rotating a key](#rotating-a-key). -- **Revoke keys immediately** if you suspect compromise, and rotate anything that depended on them. Revocation is forwarded to the storage operator, so treat it as effective quickly rather than assuming a precise cut-off instant. -- **Never hardcode credentials** in source code. Use environment variables or a secrets manager. +- **Revoke keys immediately** if you suspect compromise, and rotate anything that depended on them. Treat revocation as effective quickly rather than assuming a precise cut-off instant. +- **Never hardcode credentials** in source code. Use environment variables or a secrets manager, and keep downloaded `.env` and `.csv` credential files out of version control. +- **Don't paste keys into AI tools.** Give a coding agent its own narrowly scoped key in a named profile instead. See [Authentication](/security/authentication) for how to configure your S3 client with your API keys. diff --git a/docs/security/authentication.mdx b/docs/security/authentication.mdx index f8f162d..5b6ff78 100644 --- a/docs/security/authentication.mdx +++ b/docs/security/authentication.mdx @@ -3,10 +3,6 @@ title: Authentication description: How to authenticate with the Fil One API using API keys and SigV4. --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - All API requests to Fil One must be authenticated using AWS Signature Version 4 (SigV4). This is the same authentication method used by AWS S3, so any S3-compatible SDK or tool handles it automatically. :::note Looking for account sign-in? @@ -23,24 +19,14 @@ Each API key consists of two parts: | Component | Description | Example format | |-----------|-------------|----------------| -| **Access Key ID** | Identifies your account. Included in request headers. | `FHXXXXXXXXXXXXXXXX` | +| **Access Key ID** | Identifies the key. Included in request headers. | `FHXXXXXXXXXXXXXXXX` | | **Secret Access Key** | Signs your requests. Never sent over the wire. | `EXAMPLEfakeSECRETkeyDoNotUse...` | Your secret key is displayed **once** at creation time. Store it securely. If you lose it, [rotate the key](/security/api-keys#rotating-a-key) to get a new key pair. ## Creating an API key - - - 1. Go to **API Keys** in the left menu. - 2. Click **Create new key** (this opens a dedicated page). - 3. Give the key a descriptive name (e.g., `production-backend`, `local-dev`). Names are limited to 64 characters. - 4. Choose the **Region** the key belongs to. This is required and cannot be changed later. A key only authenticates against its own region's endpoint — a key created in the wrong region fails with `403`, which is the single most common first-run mistake. - 5. Select at least one permission (Read, Write, List, Delete), and optionally restrict the key to specific buckets and set an expiration (Never expires, 30 days, or a custom date). - 6. Click **Create API key**. - 7. Copy both the Access Key ID and Secret Access Key immediately — the secret is shown only once. - - +Create keys in the console under **API Keys** → **Create new key**. Pick the **Region** carefully: a key only authenticates against its own region's endpoint, and a key created in the wrong region fails with `403`, the most common first-run mistake. See [Creating an API key](/security/api-keys#creating-an-api-key) for the steps and what each permission allows. You can create multiple API keys per account. A key can only carry permissions your role in the organization holds, and Read only members cannot create keys. See [API Keys](/security/api-keys) for details on configuring key permissions. @@ -52,7 +38,7 @@ Go to **API Keys** in the left menu, find the key, open its **⋯** action menu, ### AWS CLI -Use **AWS CLI v2** — v1 ignores `endpoint_url` in config files. Configure credentials into a named `filone` profile (not the default), so they land where `--profile filone` will read them: +Use **AWS CLI v2**, version 2.13 or later, which reads `endpoint_url` from the profile. Configure credentials into a named `filone` profile (not the default), so they land where `--profile filone` will read them: ```bash aws configure --profile filone @@ -73,20 +59,17 @@ Then use `--profile filone` on your commands. Path-style addressing is required ### Python (boto3) -Load credentials from environment variables (recommended). Both `region_name` (SigV4 needs a signing region) and the path-style config are required: +Load credentials from the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables (recommended), which boto3 reads automatically. They're also the names the console's **Download .env** writes. Set `region_name` (SigV4 needs a signing region), path-style addressing, and SigV4 for presigned URLs: ```python import boto3 -import os from botocore.config import Config s3 = boto3.client( "s3", endpoint_url="https://s3.eu-west-1.filonecontent.com", - aws_access_key_id=os.environ["FIL_ACCESS_KEY"], - aws_secret_access_key=os.environ["FIL_SECRET_KEY"], region_name="eu-west-1", - config=Config(s3={"addressing_style": "path"}), + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) ``` @@ -102,7 +85,7 @@ s3 = boto3.client( aws_access_key_id="YOUR_ACCESS_KEY", aws_secret_access_key="YOUR_SECRET_KEY", region_name="eu-west-1", - config=Config(s3={"addressing_style": "path"}), + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) ``` @@ -115,10 +98,10 @@ const client = new S3Client({ endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", forcePathStyle: true, - credentials: { - accessKeyId: process.env.FIL_ACCESS_KEY, - secretAccessKey: process.env.FIL_SECRET_KEY, - }, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", + // Credentials come from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY }); ``` @@ -128,7 +111,6 @@ const client = new S3Client({ package main import ( - "context" "os" "github.com/aws/aws-sdk-go-v2/aws" @@ -142,8 +124,8 @@ func newClient() *s3.Client { Region: "eu-west-1", UsePathStyle: true, Credentials: credentials.NewStaticCredentialsProvider( - os.Getenv("FIL_ACCESS_KEY"), - os.Getenv("FIL_SECRET_KEY"), + os.Getenv("AWS_ACCESS_KEY_ID"), + os.Getenv("AWS_SECRET_ACCESS_KEY"), "", ), }) diff --git a/docs/security/encryption.mdx b/docs/security/encryption.mdx index 72401cb..79c5f8a 100644 --- a/docs/security/encryption.mdx +++ b/docs/security/encryption.mdx @@ -11,9 +11,9 @@ All objects stored in Fil One are encrypted at rest. Encryption is applied autom Encryption is performed by the S3 storage gateway for the region your bucket lives in, not by the Fil One console. This applies to all objects in all buckets, with no exceptions. -**Do not send encryption headers.** Fil One applies its own server-side encryption, and you cannot request a specific mode. Uploads specifying `ServerSideEncryption: aws:kms` (SSE-KMS) are **rejected in both regions**: with `InvalidRequest` in `us-east-1`, and with `AccessDenied` or `InvalidRequest` in `eu-west-1` depending on the operation (`PutObject`, `CopyObject`, and `CreateMultipartUpload` are all affected). SSE-C headers are rejected in `eu-west-1` too. Omit the header entirely, encryption is applied either way. +**Do not send encryption headers.** Fil One applies its own server-side encryption, and you cannot request a specific mode. Uploads specifying `ServerSideEncryption: aws:kms` (SSE-KMS) are **rejected in both regions**: with `InvalidRequest` in `us-east-1`, and with `AccessDenied` or `InvalidRequest` in `eu-west-1` depending on the operation (`PutObject`, `CopyObject`, and `CreateMultipartUpload` are all affected). SSE-C headers are rejected in `eu-west-1`; this is not yet confirmed in `us-east-1`, so don't send them there either. Omit encryption headers entirely: encryption is applied either way. -In `eu-west-1`, the bucket-level encryption operations (`GetBucketEncryption`, `PutBucketEncryption`, `DeleteBucketEncryption`) also return `AccessDenied`, so there is no encryption configuration to read or change there. Encryption is still always on. +The bucket-level encryption operations (`GetBucketEncryption`, `PutBucketEncryption`, `DeleteBucketEncryption`) can't be granted to any access key, in either region, so there is no encryption configuration to read or change over the API. Encryption is still always on. ## Encryption in transit @@ -25,7 +25,7 @@ This applies to all API operations, including uploads, downloads, presigned URLs Encryption keys are held by the **regional storage operator** that fulfils storage for your bucket's region, not by Fil One and not by you. You do not supply or manage encryption keys, and there is no customer-managed-key option. -If your compliance requirements depend on the specific cipher in use, or on who holds key material for a given region, contact support — those details are set by the regional operator rather than by Fil One. +If your compliance requirements depend on the specific cipher in use, or on who holds key material for a given region, [contact support](/app/support) — those details are set by the regional operator rather than by Fil One. ## Client-side encryption diff --git a/docs/storage/buckets.mdx b/docs/storage/buckets.mdx index c42a3b0..a869c36 100644 --- a/docs/storage/buckets.mdx +++ b/docs/storage/buckets.mdx @@ -15,25 +15,24 @@ Bucket names must be: - Between 3 and 63 characters - Lowercase letters, numbers, and hyphens only (**no dots**) - Must start and end with a letter or number -- Unique within Fil One +- Unique within the region +- Not starting with `filone-rag-`, which is reserved These rules are close to AWS S3's but not identical: in particular Fil One does **not** allow dots (`.`) in bucket names, which AWS S3 permits. If you are migrating a bucket whose name contains a dot, you will need to rename it. ## Creating a bucket :::note -Whether you can create a bucket through the S3 API depends on the region. `CreateBucket` and `DeleteBucket` are supported in `us-east-1`, but not in `eu-west-1` — in that region buckets must be created through the Fil One dashboard. All other S3 operations (uploading, downloading, listing objects, etc.) work normally via the API in every region. +Whether you can create a bucket through the S3 API depends on the region. `CreateBucket` and `DeleteBucket` are supported in `us-east-1`, but not in `eu-west-1` — in that region buckets must be created in the Fil One console. All other S3 operations (uploading, downloading, listing objects, etc.) work normally via the API in every region. To use `CreateBucket` or `DeleteBucket` with an access key, grant the key that permission when you create it. See [API Keys](/security/api-keys). ::: -1. From the dashboard, click **New bucket** (or open **Buckets** in the left menu), then click **Create bucket**. +1. From the dashboard, click **New bucket** to open the create form. 2. Enter a bucket name. -3. Choose a **region** — `eu-west-1` Europe (France, the default) or `us-east-1` US East (Michigan). -4. Optionally enable **Versioning**. Leave it off and the bucket keeps only the current copy of each object. -5. Optionally enable **Object Lock**, then **Retention**. Each requires the one before it, so Object Lock only becomes available once versioning is on, and retention only once Object Lock is on. Retention takes a mode (**Governance**, the default, or **Compliance**) and a duration from 1 day up to 100 years. -6. Optionally create or configure an API key in the API key section. A key belongs to a single region and must match the bucket's region. -7. Click **Create bucket** (the button reads **Create bucket and API key** if you expanded the key section). The dashboard then opens the new bucket's page. +3. Choose a **region**: `eu-west-1` Europe (France, the default) or `us-east-1` US East (Michigan). +4. Optionally expand **Advanced settings** to turn on **Versioning**, then **Object Lock**, then **Retention**. Each needs the one before it: until it's on, the next switch shows a **Needs Versioning** or **Needs Object Lock** badge. Retention takes a mode (**Governance**, the default, or **Compliance**) and a duration from 1 day up to 100 years; it starts at 15 days. Leave Versioning off and the bucket keeps only the current copy of each object. +5. Click **Create bucket**. The console opens the new bucket's page, which offers **Create API key**. A key belongs to a single region and must match the bucket's region. Every bucket is created with encryption enabled automatically. @@ -72,7 +71,7 @@ A bucket must be empty before it can be deleted, with no objects or object versi ```bash - aws s3 rb s3://my-bucket --endpoint-url https://s3.us-east-1.filonecontent.com + aws s3 rb s3://my-bucket --endpoint-url https://s3.us-east-1.filonecontent.com --region us-east-1 ``` `DeleteBucket` over the S3 API works in `us-east-1`, using a key that has the `DeleteBucket` permission. It is not available in `eu-west-1`, so use the dashboard there. diff --git a/docs/storage/object-lock.mdx b/docs/storage/object-lock.mdx index f8e02d6..13f71c0 100644 --- a/docs/storage/object-lock.mdx +++ b/docs/storage/object-lock.mdx @@ -6,13 +6,13 @@ description: Protect objects from deletion and overwrite with WORM retention pol import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -Object Lock lets you enforce Write-Once-Read-Many (WORM) protection on stored objects. Depending on the mode you choose, a locked object cannot be deleted or overwritten until its retention period expires — in **Compliance** mode, not even by the account owner. This is designed for data-retention, legal-preservation, and ransomware-protection use cases. Whether it satisfies a specific regulation is for your own compliance review to decide — see [On regulatory compliance](#on-regulatory-compliance) at the end of this page. +Object Lock lets you enforce Write-Once-Read-Many (WORM) protection on stored objects. Depending on the mode you choose, a locked object cannot be deleted or overwritten until its retention period expires — in **Compliance** mode, not even by the organization Owner. This is designed for data-retention, legal-preservation, and ransomware-protection use cases. Whether it satisfies a specific regulation is for your own compliance review to decide — see [On regulatory compliance](#on-regulatory-compliance) at the end of this page. ## Key concepts **Retention period** — A duration during which an object version cannot be deleted or overwritten. -**Compliance mode** — The strictest protection. No user, including the account owner, can shorten the retention period or delete a locked object before it expires. +**Compliance mode** — The strictest protection. No user, including the organization Owner, can shorten the retention period or delete a locked object before it expires. **Governance mode** — A softer protection. In standard S3, a caller holding a special *bypass* permission can override Governance retention and delete objects early. **Fil One does not currently expose a grantable bypass permission**, so in practice a Governance-locked object is protected for its retention period the same way a Compliance one is; the difference is that Governance is not positioned as an absolute, unbypassable guarantee at the platform level. @@ -24,12 +24,12 @@ Object Lock is **opt-in** and must be enabled at **bucket creation time**. It ca To create a bucket with Object Lock: -1. From the dashboard, click **New bucket**, then **Create bucket**. -2. Enter a bucket name. -3. Enable **Versioning**. -4. Enable **Object Lock**. -5. Select a retention mode: **Governance** (the default) or **Compliance**. -6. Set a default retention duration — from 1 day up to 100 years (36,500 days). +1. From the dashboard, click **New bucket** to open the create form. +2. Enter a bucket name and choose a region. +3. Expand **Advanced settings** and turn on **Versioning**. Until you do, Object Lock shows a **Needs Versioning** badge. +4. Turn on **Object Lock**. +5. Turn on **Retention** and select a mode: **Governance** (the default) or **Compliance**. +6. Set a default retention duration, from 1 day up to 100 years (36,500 days). It starts at 15 days. 7. Click **Create bucket**. :::warning @@ -41,7 +41,7 @@ Object Lock must be enabled at bucket creation. It cannot be added to an existin | Mode | Can it be overridden early? | Typical use | |------|-----------------------------|-------------| | **Governance** (default) | Not through any Fil One-granted permission today | Internal-policy retention, audit-friendly workflows | -| **Compliance** | No — not by anyone, including account owners | Strict, long-term immutable record-keeping | +| **Compliance** | No — not by anyone, including organization Owners | Strict, long-term immutable record-keeping | In **Compliance mode**, the retention period is absolute. No action can shorten or remove it once set. @@ -56,31 +56,38 @@ Choose your retention mode carefully **at bucket creation** — it is fixed for The default retention period set at bucket creation is applied automatically to every object uploaded to that bucket. :::info `PutObjectRetention` needs a granted permission -Setting or changing retention on an *individual* object version via `PutObjectRetention` works in **both regions**, but only with the matching granular access-key permission, which is never granted automatically. Extending a retention period is straightforward. Shortening one uses the standard S3 bypass-governance-retention mechanism, which is a protocol-level capability of the gateway and not a permission Fil One's own access keys can grant — see [Key concepts](#key-concepts). +Setting or extending retention on an *individual* object version via `PutObjectRetention` works in **both regions**, but only with the **Set retention** permission, which is never granted automatically and only an organization Owner can grant. Retention can be extended but not shortened: no Fil One access key can be granted the bypass-governance permission. See [Key concepts](#key-concepts). ::: Object Lock buckets are always versioned, so a retention call should target a specific version with `--version-id`; without it the call targets whatever the current version is (possibly a delete marker). +The examples use Governance mode. Replace `YYYY-MM-DD` with a date a day or two from now while you're testing: you can extend retention later, but on Fil One you can't shorten it in either mode, because no key can be granted the bypass permission. + +:::danger Compliance retention can't be shortened or removed +If you set `"Mode": "COMPLIANCE"`, nobody, including the organization Owner, can delete that version or shorten its retention until the date passes. The data keeps being billed until then, up to 100 years. +::: + ```bash aws s3api put-object-retention \ - --bucket my-compliance-bucket \ + --bucket my-bucket \ --key important-record.pdf \ --version-id YOUR_VERSION_ID \ - --retention '{"Mode": "COMPLIANCE", "RetainUntilDate": "2027-12-31T00:00:00Z"}' \ - --endpoint-url https://s3.us-east-1.filonecontent.com + --retention '{"Mode": "GOVERNANCE", "RetainUntilDate": "YYYY-MM-DDT00:00:00Z"}' \ + --endpoint-url https://s3.us-east-1.filonecontent.com \ + --region us-east-1 ``` ```python s3.put_object_retention( - Bucket="my-compliance-bucket", + Bucket="my-bucket", Key="important-record.pdf", VersionId="YOUR_VERSION_ID", Retention={ - "Mode": "COMPLIANCE", - "RetainUntilDate": "2027-12-31T00:00:00Z", + "Mode": "GOVERNANCE", + "RetainUntilDate": "YYYY-MM-DDT00:00:00Z", }, ) ``` @@ -95,9 +102,11 @@ The object detail page in the dashboard shows an object's retention status, and ```bash aws s3api get-object-retention \ - --bucket my-compliance-bucket \ + --bucket my-bucket \ --key important-record.pdf \ - --endpoint-url https://s3.us-east-1.filonecontent.com + --version-id YOUR_VERSION_ID \ + --endpoint-url https://s3.us-east-1.filonecontent.com \ + --region us-east-1 ``` Returns: @@ -105,8 +114,8 @@ Returns: ```json { "Retention": { - "Mode": "COMPLIANCE", - "RetainUntilDate": "2027-12-31T00:00:00Z" + "Mode": "GOVERNANCE", + "RetainUntilDate": "YYYY-MM-DDT00:00:00+00:00" } } ``` @@ -125,11 +134,11 @@ Once the bucket is empty, delete it from the dashboard in either region (Owner a ## Object Lock and API keys -`GetBucketVersioning` and `GetBucketObjectLockConfiguration` are selectable permissions that you grant when creating a key — they are not included automatically, so add them if the key needs to read a bucket's versioning or Object Lock settings. Beyond that: +`GetBucketVersioning` and `GetBucketObjectLockConfiguration` are pre-selected when you create a key. Untick them if the key shouldn't read a bucket's versioning or Object Lock settings. Beyond that: - A key with **Delete** permission can delete objects in **Governance** mode buckets once retention has expired. Fil One does not expose a bypass permission for deleting *before* expiry. - **Compliance** mode cannot be overridden by any key, regardless of permissions. -- To set retention on an individual version, grant the `PutObjectRetention` granular permission — see the [note above](#setting-per-object-retention). It is available in both regions and is never granted automatically. +- To set retention on an individual version, grant the **Set retention** permission (Owner-only to grant). See the [note above](#setting-per-object-retention). It is available in both regions and is never granted automatically. ## Object Lock during trial diff --git a/docs/storage/objects.mdx b/docs/storage/objects.mdx index fb52150..5e9e549 100644 --- a/docs/storage/objects.mdx +++ b/docs/storage/objects.mdx @@ -38,13 +38,14 @@ Objects are the files you store in Fil One. Each object consists of the file dat # Upload a file s3.upload_file("my-file.txt", "my-bucket", "my-file.txt") - # Upload with metadata - s3.put_object( - Bucket="my-bucket", - Key="report.pdf", - Body=open("report.pdf", "rb"), - ContentType="application/pdf", - ) + # Upload with metadata (report.pdf must exist) + with open("report.pdf", "rb") as f: + s3.put_object( + Bucket="my-bucket", + Key="report.pdf", + Body=f, + ContentType="application/pdf", + ) ``` @@ -114,7 +115,7 @@ When you delete an object, it is immediately removed from your Fil One account a ## Presigned URLs -Generate a temporary URL that grants time-limited access to a specific object without requiring API credentials. +Generate a temporary URL that grants time-limited access to a specific object without requiring API credentials. The `s3` client is the one from [Python (boto3)](/sdk/python#client-configuration), with `signature_version="s3v4"` set. ```python # Generate a download URL valid for 1 hour @@ -126,4 +127,8 @@ url = s3.generate_presigned_url( print(url) ``` -Presigned URLs work for both `GetObject` (downloads) and `PutObject` (uploads). +Presigned URLs work for both `GetObject` (downloads) and `PutObject` (uploads). For uploads from the AWS SDK for JavaScript, see the [checksum setting](/sdk/javascript#client-configuration) they need. + +:::warning A presigned URL is a credential +Anyone who has the URL can use it until it expires, without signing in. Share it only with the people who should have access, and keep expiry times short. A **Share** link from the console lasts at most 7 days. +::: diff --git a/docs/storage/versioning.mdx b/docs/storage/versioning.mdx index 17c37e6..6c3ed3d 100644 --- a/docs/storage/versioning.mdx +++ b/docs/storage/versioning.mdx @@ -8,9 +8,9 @@ import TabItem from '@theme/TabItem'; Versioning is **opt-in** and configured at bucket creation time. Once enabled on a bucket, it cannot be suspended or disabled. Every time you upload an object with the same key on a versioned bucket, Fil One creates a new version rather than overwriting the previous one. -This means your data is always recoverable — you can retrieve any previous state of an object using its version ID. +Overwrites, and S3 API deletes without a version ID, keep every earlier version, so you can retrieve any previous state of an object by its version ID. Deleting a specific version, including any delete in the console, removes that version permanently. -To enable versioning, turn on the **Versioning** toggle when creating a bucket in the dashboard. Versioning is required for [Object Lock](/storage/object-lock). +To enable versioning, expand **Advanced settings** when you create a bucket in the console and turn on **Versioning**. Versioning is required for [Object Lock](/storage/object-lock). ## How versions work diff --git a/docusaurus.config.js b/docusaurus.config.js index 5b548c2..fb82e4d 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -35,9 +35,13 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= "applicationCategory": "DeveloperApplication", "operatingSystem": "Any", "offers": { - "@type": "UnitPriceSpecification", - "price": "5.99", - "priceCurrency": "USD" + "@type": "Offer", + "priceSpecification": { + "@type": "UnitPriceSpecification", + "price": "5.99", + "priceCurrency": "USD", + "unitText": "TB per month" + } }, "featureList": [ "S3-compatible API", @@ -121,7 +125,7 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= { type: "html", position: "right", - value: 'Login', + value: 'Log in', }, { type: "html", diff --git a/static/llms-full.txt b/static/llms-full.txt index 0db7830..bee9b5d 100644 --- a/static/llms-full.txt +++ b/static/llms-full.txt @@ -1,13 +1,14 @@ # Fil One Documentation -> Fil One is S3-compatible object storage built for AI agents and data-intensive -> workloads. Stored on the Filecoin network, where storage providers must +> Fil One is an S3-compatible object storage platform for teams that need +> reliable, cost-effective storage. Stored on the Filecoin network, where storage providers must > continuously submit cryptographic proofs that they still hold the data they > committed to store. No egress fees on paid plans, no per-request charges, > $5.99/TB/month with a $5.99/month minimum. -> Use any S3-compatible SDK or tool — point it at your region's endpoint, -> `https://s3..filonecontent.com`, with standard Access Key ID / Secret Access Key -> auth. Endpoint, region and key must all refer to the same region. +> Standard S3 SDKs and tools work once you point them at your region's endpoint, +> `https://s3..filonecontent.com`, and enable path-style addressing, with +> standard Access Key ID / Secret Access Key auth. Some S3 features are missing +> (see S3 Compatibility). Endpoint, region and key must all refer to the same region. Critical integration notes for developers: - CreateBucket and DeleteBucket via the S3 API are region-dependent: supported @@ -18,17 +19,28 @@ Critical integration notes for developers: (virtual-hosted-style URLs are not supported) - Access keys are scoped to ONE region and cannot be used against another - Region, versioning, Object Lock and retention are fixed at bucket creation and - cannot be changed afterwards (no update-bucket operation) -- Authentication: AWS Signature Version 4 (SigV4) — all S3-compatible SDKs - handle this automatically + cannot be changed afterwards (no update-bucket operation). PutBucketVersioning, + PutBucketObjectLockConfiguration and Get/PutBucketEncryption CANNOT BE GRANTED + to any access key in either region; versioning and default retention are set + only in the console's create form (under Advanced settings) +- Bucket names are unique within the region; names starting with `filone-rag-` + are reserved +- Authentication: AWS Signature Version 4 (SigV4). In boto3 set + `Config(signature_version="s3v4")` explicitly so presigned URLs use SigV4 +- AWS SDK for JavaScript v3.729+ adds CRC32 checksums by default; set + `requestChecksumCalculation: "WHEN_REQUIRED"` and + `responseChecksumValidation: "WHEN_REQUIRED"` on the S3Client, or presigned + uploads fail with BadDigest +- Credentials: the console's Download .env uses the standard AWS_ACCESS_KEY_ID / + AWS_SECRET_ACCESS_KEY names, which every SDK reads automatically - All buckets are private by default; all data is encrypted at rest and in transit (TLS); encryption cannot be disabled. At-rest encryption is done by the regional storage gateway and keys are held by the regional operator, NOT by Fil One and NOT customer-managed. Do not name a specific cipher or SSE mode. SSE-KMS is rejected in BOTH regions (InvalidRequest in us-east-1; AccessDenied - or InvalidRequest in eu-west-1) and SSE-C is unsupported — send no encryption - headers at all. In eu-west-1, Get/PutBucketEncryption also return AccessDenied, - so no encryption configuration can be read or written there + or InvalidRequest in eu-west-1). SSE-C is rejected in eu-west-1 and not yet + confirmed in us-east-1 — send no encryption headers at all. No access key can + be granted Get/PutBucketEncryption in either region - Regions: eu-west-1 Europe (France, default) and us-east-1 US East (Michigan) - Deletion is permanent and immediate on non-versioned buckets (no recycle bin). On versioned buckets an S3-API delete WITHOUT a version ID places a delete @@ -37,23 +49,25 @@ Critical integration notes for developers: the specific version on the row chosen, even on a versioned bucket - CopyObject / server-side copy is confirmed working in us-east-1, including copying a specific version onto the current key to promote it (a version - restore). In eu-west-1 PLAIN COPY WORKS but the version-id form is UNVERIFIED - (the harness cannot configure versioning over the API there); download and - re-upload is the fallback. The dashboard has no restore/roll-back button either way + restore). In eu-west-1 PLAIN COPY WORKS but the version-id form is NOT YET + CONFIRMED; download and re-upload is the fallback. The dashboard has no restore/roll-back button either way - Per-object CIDs, deal IDs, and sealing state are NOT exposed — customers cannot independently audit an individual object - A failed payment (past_due) makes the DASHBOARD READ-ONLY from the moment the - payment fails, not after a later deadline; Stripe retries the charge + payment fails, not after a later deadline; Stripe retries the charge. An + organization OWNER can reactivate a canceled or disabled subscription from + Billing -> Reactivate (no need to contact support) - Trial caps are enforcement thresholds, not allowances: storage reaching 1 TB WRITE-LOCKS the account (lifted on the next usage run once storage is back under 1 TB); egress reaching 2 TB DISABLES it entirely, with NO read-only grace period first. Trial egress is a single cumulative budget over the 30 days. Enforced by a twice-daily job (~07:00/19:00 UTC), not in real time - Storage is DECIMAL: 1 TB = 1,000 GB, 1 GB = 1,000,000,000 bytes -- Governance Object Lock has NO grantable bypass permission in the product +- Object Lock has NO grantable bypass permission: retention can be set or + EXTENDED but NEVER SHORTENED, in either mode - PutObjectRetention (per-object retention) and Legal Hold - (Get/PutObjectLegalHold) work in BOTH REGIONS, including Governance-mode bypass - and blocking delete while a hold is active. Both need the matching granular key + (Get/PutObjectLegalHold) work in BOTH REGIONS, including blocking delete while + a hold is active. Both need the matching granular key permission, which is never granted automatically, and only an organization OWNER can create a key with PutObjectRetention or PutObjectLegalHold. Evidence differs by region: us-east-1 from the automated compatibility suite, @@ -61,8 +75,8 @@ Critical integration notes for developers: bucket there) - The S3 API has NO IAM users, roles, or bucket policies: each request is allowed or refused by the access key's own permissions and bucket scope. The CONSOLE - has organizations (BETA) with four member roles (Owner, Admin, Member, Read - only); a key can only carry permissions its creator's role holds + has organizations with four member roles (Owner, Admin, Member, Read only); a + key can only carry permissions its creator's role holds - Access keys can be ROTATED in the dashboard (new Access Key ID and secret, same name/permissions/buckets/region/expiry; old secret stops working at once) - Object/part size limits (5 TB object, 5 GB single-PUT, 10,000 parts, 5 MB min @@ -72,9 +86,10 @@ Critical integration notes for developers: S3 limit of 1,024 bytes applies but is NOT independently confirmed - In eu-west-1, UNIMPLEMENTED OPERATIONS RETURN AccessDenied (403), NOT NotImplemented (501), and a bucket/key you cannot see returns 403 instead of - 404. A 403 from PutBucketVersioning, PutBucketPolicy, PutBucketAcl, - PutBucketEncryption, PutBucketLifecycleConfiguration or the tagging operations - means the FEATURE IS ABSENT, not that the key lacks a permission + 404. A 403 from PutBucketPolicy, PutBucketAcl, PutBucketLifecycleConfiguration + or the tagging operations means the FEATURE IS ABSENT, not that the key lacks + a permission; PutBucketVersioning and PutBucketEncryption can't be granted to + any key, so they fail the same way - ACL requests fail two different ways in eu-west-1: a canned-ACL HEADER on an upload (--acl public-read) is SILENTLY IGNORED and the upload SUCCEEDS, while a DEDICATED call (Put/GetBucketAcl, Put/GetObjectAcl) is REJECTED with @@ -94,31 +109,27 @@ Critical integration notes for developers: # Welcome to Fil One -Fil One is an S3-compatible object storage platform designed for teams that need -reliable, cost-effective storage with built-in compliance features. If you've used -AWS S3, you already know how to use Fil One. +Source: https://docs.filone.com/ + +Fil One is an S3-compatible object storage platform designed for teams that need reliable, cost-effective storage, with Object Lock for write-once retention. If you've used AWS S3, you already know how to use Fil One. + +## Get started + +- [Quickstart](https://docs.filone.com/quickstart): Go from signup to your first upload. +- [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility): See which S3 operations are supported and how to connect. +- [SDK Examples](https://docs.filone.com/sdk/overview): Copy-paste code examples for Python, JavaScript, Go, and CLI. ## Why Fil One -**S3-compatible from day one.** Use the tools you already know — AWS CLI, boto3, -any S3-compatible SDK. Point your existing code at our endpoint and it works. +**S3-compatible from day one.** Use the tools you already know — AWS CLI, boto3, any S3-compatible SDK. Point your existing code at your region's endpoint, turn on path-style addressing, and it works. See [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility) for the operations Fil One does not support. -**Backed by Filecoin.** Fil One stores your data on Filecoin, a distributed -storage network where storage providers must continuously submit cryptographic -proofs that they are still holding the data they committed to store, or face -penalties. Note that this proof cycle is a property of the network — Fil One does -not expose per-object CIDs, deal IDs, or sealing state, so an individual object -cannot be independently audited by the customer today. +**Backed by Filecoin.** Fil One stores your data on Filecoin, a distributed storage network where storage providers must continuously submit cryptographic proofs that they are still holding the data they committed to store, or face penalties. -**No egress fees on paid plans.** On a paid plan there are no data-transfer -charges. (The free trial has a 2 TB egress cap.) +**No egress fees on paid plans.** On a paid plan there are no data-transfer charges — download as much as you need. (The free trial has a 2 TB egress cap; see [Trial & Billing](https://docs.filone.com/billing/trial).) -**Simple, flat pricing.** Pay as you go at $5.99 / TB / month, with a $5.99 / -month minimum. No per-request charges, no hidden fees, no tiered pricing. For -volume pricing on 1, 3, or 5-year terms, talk to sales about the Business plan. +**Simple, flat pricing.** Pay as you go at $5.99 / TB / month, with a $5.99 / month minimum. No per-request charges, no hidden fees, no tiered pricing. For volume pricing on 1, 3, or 5-year terms, talk to sales about the Business plan. -**30-day free trial.** 1 TB of storage and 2 TB of bandwidth, no credit card -required. +**30-day free trial.** 1 TB of storage and 2 TB of bandwidth, no credit card required. --- @@ -127,87 +138,99 @@ required. Source: https://docs.filone.com/quickstart -This guide walks you through creating an account, setting up credentials, and -uploading your first object. +This guide walks you through creating an account, setting up credentials, and uploading your first object. Choose the path that fits your workflow. ## 1. Create your account -1. Go to app.filone.com and sign up with your email or SSO. +1. Go to [app.filone.com](https://app.filone.com) and sign up with your email, Google, or GitHub. 2. Verify your email address. -3. No credit card needed — your 30-day free trial starts automatically. +3. You're in. No credit card needed — your 30-day free trial starts automatically. ## 2. Create a bucket -From the dashboard, click **New bucket**, then **Create bucket**. Give it a name -(lowercase letters, numbers, and hyphens — no dots, unlike AWS S3) and choose -your settings: - -- Region: eu-west-1 Europe (France, default) or us-east-1 US East (Michigan) -- Encryption: Always on (all data is encrypted at rest by default) -- Versioning: off by default -- Object Lock: off by default, requires versioning -- Retention: off by default, requires Object Lock - -Region, versioning, Object Lock and retention are ALL fixed at creation. They -cannot be changed on an existing bucket and a bucket cannot be moved between -regions — you would have to create a new bucket and copy the data across. - -The three object settings nest and are enabled in order: versioning first -(Object Lock is greyed out until it is on), then Object Lock (retention is greyed -out until it is on), then retention. Retention modes: Governance (default — in -standard S3 a bypass permission can override it, but Fil One exposes no grantable -bypass permission, so in practice it protects for the retention period) and -Compliance (no one, including the account owner, can delete or modify objects -until the retention period expires). Duration is set in days or years, from 1 day -up to 100 years. - -You will also see an API key section during bucket creation. You can create a new -API key here or configure permissions for an existing one. A key belongs to a -single region and must match the bucket's region. +From the dashboard, click **New bucket** to open the create form. Give the bucket a name (lowercase letters, numbers, and hyphens; unlike AWS S3, Fil One does **not** allow dots) and pick a region: + +| Setting | Options | Notes | +|---------|---------|-------| +| Region | `eu-west-1` Europe (France) or `us-east-1` US East (Michigan) | Defaults to `eu-west-1`. Cannot be changed later. | +| Encryption | Always on | All data is encrypted at rest. Nothing to configure. | + +Leave everything else at its default for your first bucket, and click **Create bucket**. + +Warning: Some settings can only be chosen now +Versioning, Object Lock, and retention sit under **Advanced settings** on the create form, and can only be turned on when the bucket is created. Neither can be turned off later, and Object Lock can stop you deleting data you're paying for. Read [Versioning](https://docs.filone.com/storage/versioning) and [Object Lock](https://docs.filone.com/storage/object-lock) before you enable them on a bucket you plan to keep. ## 3. Upload your first object -Go to **API Keys** in the left menu and click **Create new key**. You'll get two values: +Choose your preferred method. The App requires no API key. For CLI and SDK access, open your new bucket and click **Create API key**, or go to **API Keys** in the left menu and click **Create new key**. You'll get two values: -- **Access Key ID** — identifies your account (safe to store in config) +- **Access Key ID** — identifies the key (safe to store in config) - **Secret Access Key** — authenticates your requests (treat like a password) -Your secret key is shown once. Copy it and store it securely. If you lose it, -rotate the key from its ⋯ menu in API Keys to get a new secret. +Note: +Your secret key is shown once. Copy it and store it securely. If you lose it, rotate the key from its **⋯** menu in **API Keys** to get a new secret. See [API Keys](https://docs.filone.com/app/api-keys#rotating-a-key). -### AWS CLI +A key also belongs to a single region, so create it in the same region as your bucket. + +The examples below use `eu-west-1`, the default region. For a bucket in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and region `us-east-1` instead. + +App: +1. Open your bucket from the dashboard. +2. Click **Upload object**, select one or more files (or drag a whole folder in), then click **Upload** to start the transfer. +3. Your objects appear in the file list once the upload completes. +4. To download: click the download icon on the object's row, or open the object's detail page and use the **Download** button in the header. + +AWS CLI: +Create a `filone` profile so you don't overwrite your default AWS credentials. Requires [AWS CLI v2](https://docs.filone.com/sdk/cli). Enter your key's ID and secret when prompted, and leave the other prompts empty: ```bash -aws configure set aws_access_key_id YOUR_ACCESS_KEY -aws configure set aws_secret_access_key YOUR_SECRET_KEY -aws configure set default.region eu-west-1 +aws configure --profile filone +aws configure set region eu-west-1 --profile filone +aws configure set endpoint_url https://s3.eu-west-1.filonecontent.com --profile filone +# Path-style is required: Fil One does not support virtual-hosted URLs +aws configure set s3.addressing_style path --profile filone +``` -aws s3 cp my-file.txt s3://my-bucket/my-file.txt \ - --endpoint-url https://s3.eu-west-1.filonecontent.com +Upload a file: -aws s3 ls s3://my-bucket/ --endpoint-url https://s3.eu-west-1.filonecontent.com +```bash +echo "hello" > my-file.txt +aws s3 cp my-file.txt s3://my-bucket/my-file.txt --profile filone ``` -### Python (boto3) +Verify it's there: + +```bash +aws s3 ls s3://my-bucket/ --profile filone +``` + +Python (boto3): +Create `my-file.txt` first, for example with `echo "hello" > my-file.txt`. ```python import boto3 +from botocore.config import Config s3 = boto3.client( "s3", endpoint_url="https://s3.eu-west-1.filonecontent.com", aws_access_key_id="YOUR_ACCESS_KEY", aws_secret_access_key="YOUR_SECRET_KEY", + region_name="eu-west-1", + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) +# Upload a file s3.upload_file("my-file.txt", "my-bucket", "my-file.txt") +# List objects to confirm response = s3.list_objects_v2(Bucket="my-bucket") for obj in response.get("Contents", []): print(obj["Key"], obj["Size"]) ``` -### JavaScript (AWS SDK v3) +JavaScript (AWS SDK v3): +Save this as `upload.mjs` (it uses ES modules and top-level `await`), then run `node upload.mjs`: ```javascript import { S3Client, PutObjectCommand, ListObjectsV2Command } from "@aws-sdk/client-s3"; @@ -217,68 +240,34 @@ const client = new S3Client({ endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", forcePathStyle: true, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", credentials: { accessKeyId: "YOUR_ACCESS_KEY", secretAccessKey: "YOUR_SECRET_KEY", }, }); +// Upload a file await client.send(new PutObjectCommand({ Bucket: "my-bucket", Key: "my-file.txt", Body: readFileSync("my-file.txt"), })); +// List objects to confirm const { Contents } = await client.send( new ListObjectsV2Command({ Bucket: "my-bucket" }) ); Contents?.forEach((obj) => console.log(obj.Key, obj.Size)); ``` -### Go (aws-sdk-go-v2) - -```go -package main - -import ( - "context" - "fmt" - "os" - "strings" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/credentials" - "github.com/aws/aws-sdk-go-v2/service/s3" -) - -func main() { - client := s3.New(s3.Options{ - BaseEndpoint: aws.String("https://s3.eu-west-1.filonecontent.com"), - Region: "eu-west-1", - UsePathStyle: true, - Credentials: credentials.NewStaticCredentialsProvider( - os.Getenv("FIL_ACCESS_KEY"), - os.Getenv("FIL_SECRET_KEY"), - "", - ), - }) - - ctx := context.Background() - - client.PutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String("my-bucket"), - Key: aws.String("hello.txt"), - Body: strings.NewReader("Hello from Go!"), - }) +## What's next - out, _ := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{ - Bucket: aws.String("my-bucket"), - }) - for _, obj := range out.Contents { - fmt.Printf("%s (%d bytes)\n", *obj.Key, *obj.Size) - } -} -``` +- [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility): Full list of supported operations and headers. +- [SDK Examples](https://docs.filone.com/sdk/overview): Detailed examples for Python, JavaScript, Go, and CLI. +- [Billing & Trial](https://docs.filone.com/billing/trial): What's included in your trial and how to upgrade. --- @@ -287,37 +276,38 @@ func main() { Source: https://docs.filone.com/quickstart/cli -If you have the AWS CLI installed, you can start using Fil One in under 2 minutes. - -```bash -# Install -pip install awscli -# or -brew install awscli +Use the AWS CLI to upload, list and download objects in a Fil One bucket. You need a Fil One account and an API key. To create a key, open **API Keys** in the [console](https://app.filone.com), click **Create new key**, and pick the same region as your bucket. The secret is shown once. -# Configure -aws configure -# Enter your Fil One access key and secret key. Set region to eu-west-1. +## 1. Install the AWS CLI -# Upload -aws s3 cp my-file.txt s3://my-first-bucket/ --endpoint-url https://s3.eu-west-1.filonecontent.com +Use **AWS CLI v2**, version 2.13 or later, so the CLI reads `endpoint_url` from your profile: -# List -aws s3 ls s3://my-first-bucket/ --endpoint-url https://s3.eu-west-1.filonecontent.com - -# Download -aws s3 cp s3://my-first-bucket/my-file.txt ./downloaded.txt --endpoint-url https://s3.eu-west-1.filonecontent.com +```bash +brew install awscli +# or follow the official installer: +# https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html ``` -Tip: Set up a named profile to avoid repeating --endpoint-url: +## 2. Configure credentials + +Set up a named profile, so you don't overwrite your default AWS credentials and don't have to pass `--endpoint-url` on every command: ```ini # ~/.aws/config [profile filone] endpoint_url = https://s3.eu-west-1.filonecontent.com region = eu-west-1 +s3 = + addressing_style = path ``` +The `addressing_style = path` line is required — Fil One only supports path-style URLs, and the CLI otherwise defaults to virtual-hosted style, which fails. + +Note: The endpoint depends on your bucket's region +The example above uses `eu-west-1`, the default region. If your bucket is in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and `region = us-east-1` instead. The endpoint and the region must both match the bucket you are working with, and your access key has to belong to that region too. + +If you use both regions, set up a profile per region (`[profile filone-eu]`, `[profile filone-us]`) and pick with `--profile`. + ```ini # ~/.aws/credentials [filone] @@ -325,10 +315,37 @@ aws_access_key_id = YOUR_ACCESS_KEY aws_secret_access_key = YOUR_SECRET_KEY ``` -Then use `--profile filone` on every command: +## 3. Create a bucket + +Whether `CreateBucket` works through the S3 API depends on the region. It is **not** available in `eu-west-1`, the default region. There, create the bucket in the [Fil One console](https://app.filone.com): click **New bucket**, enter `my-bucket` (or your own name), and click **Create bucket**. + +In `us-east-1` you can create a bucket from the CLI, using a key that has the `CreateBucket` permission. This requires a `us-east-1` profile — define one the same way as the `filone` profile above but with the `us-east-1` endpoint and region (shown here as `filone-us`): ```bash -aws s3 ls --profile filone +aws s3 mb s3://my-bucket --profile filone-us +``` + +Versioning and Object Lock can only be turned on when you create the bucket in the console. See [Buckets](https://docs.filone.com/storage/buckets). + +The steps below use the `filone` profile (`eu-west-1`). If your bucket is in `us-east-1`, use `--profile filone-us` instead: the profile, the key and the bucket must all be in the same region. + +## 4. Upload a file + +```bash +echo "hello" > my-file.txt +aws s3 cp my-file.txt s3://my-bucket/ --profile filone +``` + +## 5. List objects + +```bash +aws s3 ls s3://my-bucket/ --profile filone +``` + +## 6. Download the file + +```bash +aws s3 cp s3://my-bucket/my-file.txt ./downloaded.txt --profile filone ``` @@ -338,17 +355,21 @@ aws s3 ls --profile filone Source: https://docs.filone.com/quickstart/sdk -Each example uploads a file and verifies it. Create the bucket first in the -dashboard — CreateBucket over the S3 API is not available in eu-west-1, the -default region these examples use. +Choose your language and follow along. Each example uploads a file and verifies it. **Create the bucket first in the dashboard** — `CreateBucket` over the S3 API is not available in `eu-west-1`, the default region these examples use. + +Note: The endpoint depends on your bucket's region +These examples use `eu-west-1`, the default region. For a bucket in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and region `us-east-1`. The endpoint, the region, and your access key must all refer to the same region. -Note: the endpoint depends on your bucket's region. These examples use -eu-west-1, the default. For a bucket in us-east-1, use -https://s3.us-east-1.filonecontent.com and region us-east-1. The endpoint, the region, and -your access key must all refer to the same region. +Each example reads your key from the standard AWS environment variables, the same names the console's **Download .env** writes. Set them in your shell before you run an example, and keep the secret out of your code: + +```bash +export AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY +export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY +``` -## Python +The Python and JavaScript examples upload `my-file.txt`, so create it first: `echo "hello" > my-file.txt`. +Python: ```bash pip install boto3 ``` @@ -360,27 +381,27 @@ from botocore.config import Config s3 = boto3.client( "s3", endpoint_url="https://s3.eu-west-1.filonecontent.com", - aws_access_key_id="YOUR_ACCESS_KEY", - aws_secret_access_key="YOUR_SECRET_KEY", region_name="eu-west-1", - config=Config(s3={"addressing_style": "path"}), + # Credentials come from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) # Upload a file (create the bucket first in the dashboard) -s3.upload_file("my-file.txt", "my-sdk-bucket", "my-file.txt") +s3.upload_file("my-file.txt", "my-bucket", "my-file.txt") # Verify -response = s3.list_objects_v2(Bucket="my-sdk-bucket") +response = s3.list_objects_v2(Bucket="my-bucket") for obj in response.get("Contents", []): print(f"{obj['Key']} ({obj['Size']} bytes)") ``` -## JavaScript - +JavaScript: ```bash npm install @aws-sdk/client-s3 ``` +Save this as `upload.mjs` (it uses ES modules and top-level `await`), then run `node upload.mjs`: + ```javascript import { S3Client, PutObjectCommand, ListObjectsV2Command } from "@aws-sdk/client-s3"; import { readFileSync } from "fs"; @@ -389,39 +410,43 @@ const client = new S3Client({ endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", forcePathStyle: true, - credentials: { - accessKeyId: "YOUR_ACCESS_KEY", - secretAccessKey: "YOUR_SECRET_KEY", - }, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", + // Credentials come from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY }); // Upload a file (create the bucket first in the dashboard) await client.send(new PutObjectCommand({ - Bucket: "my-sdk-bucket", + Bucket: "my-bucket", Key: "my-file.txt", Body: readFileSync("my-file.txt"), })); // Verify const { Contents } = await client.send( - new ListObjectsV2Command({ Bucket: "my-sdk-bucket" }) + new ListObjectsV2Command({ Bucket: "my-bucket" }) ); Contents?.forEach((obj) => console.log(obj.Key, obj.Size)); ``` -## Go - +Go: ```bash +mkdir filone-quickstart && cd filone-quickstart +go mod init example.com/filone-quickstart go get github.com/aws/aws-sdk-go-v2/service/s3 go get github.com/aws/aws-sdk-go-v2/credentials ``` +Save this as `main.go` and run `go run .`: + ```go package main import ( "context" "fmt" + "log" "os" "strings" @@ -436,8 +461,8 @@ func main() { Region: "eu-west-1", UsePathStyle: true, Credentials: credentials.NewStaticCredentialsProvider( - os.Getenv("FIL_ACCESS_KEY"), - os.Getenv("FIL_SECRET_KEY"), + os.Getenv("AWS_ACCESS_KEY_ID"), + os.Getenv("AWS_SECRET_ACCESS_KEY"), "", ), }) @@ -445,24 +470,33 @@ func main() { ctx := context.Background() // Upload (create the bucket first in the dashboard) - client.PutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String("my-sdk-bucket"), + _, err := client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String("my-bucket"), Key: aws.String("hello.txt"), Body: strings.NewReader("Hello from Go!"), }) + if err != nil { + log.Fatal(err) + } // List - out, _ := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{ - Bucket: aws.String("my-sdk-bucket"), + out, err := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{ + Bucket: aws.String("my-bucket"), }) + if err != nil { + log.Fatal(err) + } for _, obj := range out.Contents { fmt.Printf("%s (%d bytes)\n", *obj.Key, *obj.Size) } } ``` -For more detailed examples including multipart uploads and presigned URLs, see -the dedicated SDK pages for Python, JavaScript, and Go. +For more detailed examples including multipart uploads and presigned URLs, see the dedicated SDK pages: + +- [Python](https://docs.filone.com/sdk/python): boto3: uploads, downloads, multipart, presigned URLs. +- [JavaScript](https://docs.filone.com/sdk/javascript): AWS SDK v3: the same operations from Node.js. +- [Go](https://docs.filone.com/sdk/go): aws-sdk-go-v2: the same operations from Go. --- @@ -475,37 +509,41 @@ Buckets are containers for your objects. Every object in Fil One lives inside a ## Bucket naming rules +Bucket names must be: - Between 3 and 63 characters -- Lowercase letters, numbers, and hyphens only (no dots) +- Lowercase letters, numbers, and hyphens only (**no dots**) - Must start and end with a letter or number -- Unique within Fil One +- Unique within the region +- Not starting with `filone-rag-`, which is reserved -These rules are close to AWS S3's but not identical: Fil One does NOT allow dots -(.) in bucket names, which AWS S3 permits. A bucket named `my.data.bucket` must be -renamed when migrating. +These rules are close to AWS S3's but not identical: in particular Fil One does **not** allow dots (`.`) in bucket names, which AWS S3 permits. If you are migrating a bucket whose name contains a dot, you will need to rename it. ## Creating a bucket -Whether you can create or delete a bucket through the S3 API depends on the -region: CreateBucket and DeleteBucket are supported in us-east-1 but not in -eu-west-1, where buckets are created through the Fil One dashboard. All other S3 -operations work normally via the API in every region. To use CreateBucket or -DeleteBucket with an access key, grant the key that permission at creation. +Note: +Whether you can create a bucket through the S3 API depends on the region. `CreateBucket` and `DeleteBucket` are supported in `us-east-1`, but not in `eu-west-1` — in that region buckets must be created in the Fil One console. All other S3 operations (uploading, downloading, listing objects, etc.) work normally via the API in every region. + +To use `CreateBucket` or `DeleteBucket` with an access key, grant the key that permission when you create it. See [API Keys](https://docs.filone.com/security/api-keys). -1. From the dashboard, click **New bucket**, then **Create bucket**. +1. From the dashboard, click **New bucket** to open the create form. 2. Enter a bucket name. -3. Choose a region, and optionally enable versioning → Object Lock → retention (all permanent), and create or configure an API key. -4. Click **Create bucket** (it reads **Create bucket and API key** if you expanded - the key section). The dashboard then opens the new bucket's page. +3. Choose a **region**: `eu-west-1` Europe (France, the default) or `us-east-1` US East (Michigan). +4. Optionally expand **Advanced settings** to turn on **Versioning**, then **Object Lock**, then **Retention**. Each needs the one before it: until it's on, the next switch shows a **Needs Versioning** or **Needs Object Lock** badge. Retention takes a mode (**Governance**, the default, or **Compliance**) and a duration from 1 day up to 100 years; it starts at 15 days. Leave Versioning off and the bucket keeps only the current copy of each object. +5. Click **Create bucket**. The console opens the new bucket's page, which offers **Create API key**. A key belongs to a single region and must match the bucket's region. Every bucket is created with encryption enabled automatically. +Warning: Creation-time settings are permanent +Region, versioning, Object Lock, and retention cannot be changed after the bucket exists — there is no update-bucket operation, and a bucket cannot be moved between regions. To change any of them you have to create a new bucket and copy the data across. Enable versioning and Object Lock now if you are likely to want them. + ## Listing buckets +AWS CLI: ```bash aws s3 ls --endpoint-url https://s3.eu-west-1.filonecontent.com ``` +Python (boto3): ```python response = s3.list_buckets() for bucket in response["Buckets"]: @@ -514,27 +552,22 @@ for bucket in response["Buckets"]: ## Deleting a bucket -A bucket must be EMPTY before it can be deleted, with no objects or object -versions left in it. +A bucket must be empty before it can be deleted, with no objects or object versions left in it. + +App: +Open **Buckets**, choose **Delete bucket** from the bucket's actions menu, and confirm. If the bucket still holds objects, the dashboard tells you it is not empty. Open the bucket and use **Empty bucket** to remove everything first. See [Buckets in the console](https://docs.filone.com/app/buckets#deleting-a-bucket). -- Dashboard: open **Buckets**, choose **Delete bucket** from the bucket's actions - menu, and confirm. If the bucket still holds objects, the dashboard says it is - not empty; open the bucket and use **Empty bucket** to remove everything first. - Dashboard deletion works in EVERY region, including eu-west-1. Only the Owner - and Admin roles can delete buckets. -- S3 API: DeleteBucket works in us-east-1, using a key that has the DeleteBucket - permission. It is NOT available in eu-west-1, so use the dashboard there. +Dashboard deletion works in every region, including `eu-west-1`. Only the Owner and Admin roles can delete buckets. +AWS CLI: ```bash -aws s3 rb s3://my-bucket --endpoint-url https://s3.us-east-1.filonecontent.com +aws s3 rb s3://my-bucket --endpoint-url https://s3.us-east-1.filonecontent.com --region us-east-1 ``` -Note: When you delete a bucket and its objects, the data is immediately removed -from your Fil One account. Because Filecoin stores data in sealed sectors, the -underlying storage may persist for a bounded period until the sector naturally -expires (duration set by the storage layer). That residual data stays encrypted, -and key custody sits with the regional storage operator rather than with you or -Fil One. This does not affect your ability to manage your data in Fil One. +`DeleteBucket` over the S3 API works in `us-east-1`, using a key that has the `DeleteBucket` permission. It is not available in `eu-west-1`, so use the dashboard there. + +Info: Logical deletion and Filecoin storage +When you delete a bucket and its objects, the data is immediately removed from your Fil One account and is no longer accessible via the API or dashboard. Because Filecoin stores data in sealed sectors, the underlying storage may persist for a bounded period after deletion before it naturally expires. That residual data stays encrypted, and key custody sits with the regional storage operator rather than with you or Fil One — see [Encryption](https://docs.filone.com/security/encryption). The exact duration is set by the storage layer rather than measured by Fil One, and it does not affect your ability to manage your data in Fil One. --- @@ -543,11 +576,19 @@ Fil One. This does not affect your ability to manage your data in Fil One. Source: https://docs.filone.com/storage/objects -Objects are the files you store in Fil One. Each object consists of the file data, -a key (the file path/name), and metadata. +Objects are the files you store in Fil One. Each object consists of the file data, a key (the file path/name), and metadata. ## Uploading objects +App: +1. Open a bucket from the dashboard. +2. Click **Upload object**. +3. Select one or more files, or drag a whole folder in (an optional prefix lets you upload into a subpath), then click **Upload** to start the transfer. +4. Objects appear in the file list once the upload completes. + +Folder uploads skip system files such as `.DS_Store`, `Thumbs.db`, dot-files, and `__MACOSX` folders, and tell you how many were skipped. See [Uploading](https://docs.filone.com/app/buckets#uploading). + +AWS CLI: ```bash # Upload a single file aws s3 cp my-file.txt s3://my-bucket/my-file.txt \ @@ -558,31 +599,35 @@ aws s3 sync ./local-folder s3://my-bucket/folder/ \ --endpoint-url https://s3.eu-west-1.filonecontent.com ``` +Python (boto3): ```python # Upload a file s3.upload_file("my-file.txt", "my-bucket", "my-file.txt") -# Upload with metadata -s3.put_object( - Bucket="my-bucket", - Key="report.pdf", - Body=open("report.pdf", "rb"), - ContentType="application/pdf", -) +# Upload with metadata (report.pdf must exist) +with open("report.pdf", "rb") as f: + s3.put_object( + Bucket="my-bucket", + Key="report.pdf", + Body=f, + ContentType="application/pdf", + ) ``` -For very large objects (above the single-PUT limit — the standard S3 5 GB, not independently confirmed for Fil One), use multipart upload. - -In the dashboard, folder uploads skip system files such as `.DS_Store`, -`Thumbs.db`, dot-files, and `__MACOSX` folders, and tell you how many were skipped. +For very large objects (above the single-PUT limit — see [Limits](https://docs.filone.com/limits)), use [multipart upload](https://docs.filone.com/storage/multipart-uploads). ## Downloading objects +App: +Click the download icon directly on the object's row in the file list, or click the file name to open its detail page and use the **Download** button in the header. + +AWS CLI: ```bash aws s3 cp s3://my-bucket/my-file.txt ./my-file.txt \ --endpoint-url https://s3.eu-west-1.filonecontent.com ``` +Python (boto3): ```python s3.download_file("my-bucket", "my-file.txt", "my-file.txt") ``` @@ -593,7 +638,7 @@ s3.download_file("my-bucket", "my-file.txt", "my-file.txt") aws s3 ls s3://my-bucket/ --endpoint-url https://s3.eu-west-1.filonecontent.com ``` -Programmatic listing with pagination: +For programmatic listing with pagination: ```python paginator = s3.get_paginator("list_objects_v2") @@ -604,28 +649,27 @@ for page in paginator.paginate(Bucket="my-bucket"): ## Deleting objects +App: +Click the trash icon on an object's row, then confirm in the dialog. To delete several at once, tick their checkboxes and click **Delete** in the selection bar. To remove everything, including every earlier version, open the bucket and click **Empty bucket**. See [Deleting objects](https://docs.filone.com/app/buckets#deleting-objects). + +The console deletes the specific version on the row you chose, so on a versioned bucket it removes that version permanently rather than writing a delete marker. + +AWS CLI: ```bash aws s3 rm s3://my-bucket/my-file.txt \ --endpoint-url https://s3.eu-west-1.filonecontent.com ``` -In the dashboard: click the trash icon on an object's row and confirm. To delete -several at once, tick their checkboxes and click **Delete** in the selection bar. -To remove everything, including every earlier version, open the bucket and click -**Empty bucket**. +On a bucket without versioning, deletion is immediate — the object disappears from the dashboard and API instantly, and there is no recycle bin or soft-delete. -On a bucket without versioning, deletion is immediate — the object disappears from -the dashboard and API instantly, and there is no recycle bin or soft-delete. On a -versioned bucket, a delete over the S3 API WITHOUT a version ID places a delete -marker instead: prior versions are retained, downloadable by version ID, and still -counted as stored storage. The DASHBOARD deletes the specific version on the row -you chose, so on a versioned bucket it removes that version PERMANENTLY rather -than writing a delete marker. +On a [versioned](https://docs.filone.com/storage/versioning) bucket, a delete over the S3 API without a version ID places a delete marker instead: the object stops appearing in listings, but prior versions are retained, remain downloadable by version ID, and continue to count as stored storage. + +Info: Logical deletion and Filecoin storage +When you delete an object, it is immediately removed from your Fil One account and is no longer accessible. Because Filecoin stores data in sealed sectors, the underlying storage may persist for a bounded period after deletion before it naturally expires. That residual data stays encrypted, and key custody sits with the regional storage operator rather than with you or Fil One — see [Encryption](https://docs.filone.com/security/encryption). The exact duration is set by the storage layer rather than measured by Fil One, and it does not affect your ability to manage your data in Fil One. ## Presigned URLs -Generate a temporary URL that grants time-limited access to a specific object -without requiring API credentials. +Generate a temporary URL that grants time-limited access to a specific object without requiring API credentials. The `s3` client is the one from [Python (boto3)](https://docs.filone.com/sdk/python#client-configuration), with `signature_version="s3v4"` set. ```python # Generate a download URL valid for 1 hour @@ -634,9 +678,13 @@ url = s3.generate_presigned_url( Params={"Bucket": "my-bucket", "Key": "shared-report.pdf"}, ExpiresIn=3600, ) +print(url) ``` -Presigned URLs work for both GetObject (downloads) and PutObject (uploads). +Presigned URLs work for both `GetObject` (downloads) and `PutObject` (uploads). For uploads from the AWS SDK for JavaScript, see the [checksum setting](https://docs.filone.com/sdk/javascript#client-configuration) they need. + +Warning: A presigned URL is a credential +Anyone who has the URL can use it until it expires, without signing in. Share it only with the people who should have access, and keep expiry times short. A **Share** link from the console lasts at most 7 days. --- @@ -645,34 +693,39 @@ Presigned URLs work for both GetObject (downloads) and PutObject (uploads). Source: https://docs.filone.com/storage/multipart-uploads -For very large objects you must use multipart upload. The single-PUT ceiling is -the standard S3 5 GB, which Fil One's gateway is expected to follow but which is -not independently confirmed. Recommended for any file over 100 MB for improved -reliability. Note: the dashboard uploads with a single PUT, so multipart applies -when using your own SDK/CLI; there is no lifecycle rule to auto-abort incomplete -uploads. The 5 TB / 10,000-part / 5 MB-5 GB part limits are standard S3 values, -not independently confirmed. +For very large objects you must use multipart upload. Under standard S3 behaviour the single-PUT ceiling is 5 GB — this is an AWS S3 limit that Fil One's storage gateway is expected to follow but that we have not independently confirmed (see [Limits](https://docs.filone.com/limits)). Multipart upload is also recommended for any file over 100 MB for improved reliability -- if a part fails, you retry only that part instead of the entire file. + +Note: +The Fil One dashboard uploads objects with a single PUT, so multipart applies when you use your own S3 SDK or the AWS CLI, not the console upload flow. ## How it works 1. **Initiate** the upload and receive an upload ID. 2. **Upload parts** individually (minimum 5 MB each, except the last part). -3. **Complete** the upload by listing all parts. +3. **Complete** the upload by listing all parts. The service assembles the final object. + +If something goes wrong, **abort** the upload to clean up incomplete parts. -## AWS CLI +## Example: AWS CLI The AWS CLI handles multipart uploads automatically for large files: ```bash +# The AWS CLI switches to multipart above its own client-side threshold (8 MB by default) aws s3 cp large-file.zip s3://my-bucket/large-file.zip \ --endpoint-url https://s3.eu-west-1.filonecontent.com +``` + +To control thresholds: -# Configure thresholds +```bash aws configure set s3.multipart_threshold 100MB aws configure set s3.multipart_chunksize 50MB ``` -## Python (boto3) +## Example: Python (boto3) + +boto3 also handles multipart automatically via `upload_file`: ```python from boto3.s3.transfer import TransferConfig @@ -683,7 +736,12 @@ config = TransferConfig( max_concurrency=10, ) -s3.upload_file("large-file.zip", "my-bucket", "large-file.zip", Config=config) +s3.upload_file( + "large-file.zip", + "my-bucket", + "large-file.zip", + Config=config, +) ``` ## Limits @@ -695,13 +753,17 @@ s3.upload_file("large-file.zip", "my-bucket", "large-file.zip", Config=config) | Minimum part size | 5 MB (except last part) | | Maximum part size | 5 GB | +Note: +These are the standard AWS S3 multipart limits. Fil One's storage gateway is expected to follow them, but we have not independently confirmed the exact values — treat them as guidance and test against your own workload before hard-coding a part size. See [Limits](https://docs.filone.com/limits). + ## Cleaning up incomplete uploads -Key permissions for cleanup: listing in-progress uploads needs **List**, aborting -one needs **Write**, and listing the parts of an upload goes with **Read**. In -us-east-1, access keys created before 26 August 2026 do NOT carry these multipart -actions, so list-multipart-uploads and abort-multipart-upload fail with 403. -Existing keys cannot be updated: delete the key and create a new one. +Incomplete multipart uploads are generally expected to consume storage until aborted. Fil One has **no lifecycle-rule mechanism** to expire them automatically (there is no `AbortIncompleteMultipartUpload` lifecycle support), so you must list and abort stale uploads yourself: + +Note: Key permissions for cleanup +Listing in-progress uploads needs the **List** permission on your access key, and aborting one needs **Write**. Listing the parts of an upload goes with **Read**. + +In `us-east-1`, access keys created before 26 August 2026 do not carry these multipart actions, so `list-multipart-uploads` and `abort-multipart-upload` fail with `403`. Existing keys cannot be updated: delete the key and create a new one to pick them up. See [API Keys](https://docs.filone.com/security/api-keys). ```bash aws s3api list-multipart-uploads \ @@ -722,47 +784,43 @@ aws s3api abort-multipart-upload \ Source: https://docs.filone.com/storage/versioning -Versioning is opt-in and configured at bucket creation time. Once enabled on a -bucket it cannot be suspended or disabled. Every upload to an existing key on a -versioned bucket creates a new version rather than overwriting the previous one, -so any previous state of an object can be retrieved by its version ID. -Versioning is required for Object Lock. +Versioning is **opt-in** and configured at bucket creation time. Once enabled on a bucket, it cannot be suspended or disabled. Every time you upload an object with the same key on a versioned bucket, Fil One creates a new version rather than overwriting the previous one. + +Overwrites, and S3 API deletes without a version ID, keep every earlier version, so you can retrieve any previous state of an object by its version ID. Deleting a specific version, including any delete in the console, removes that version permanently. + +To enable versioning, expand **Advanced settings** when you create a bucket in the console and turn on **Versioning**. Versioning is required for [Object Lock](https://docs.filone.com/storage/object-lock). ## How versions work -The first upload of `reports/q1.pdf` creates version v1; a later upload of the -same key creates v2 and leaves v1 intact. Deleting the object over the S3 API -WITHOUT a version ID places a delete marker at the current version — the object -appears deleted, but all previous versions are still retrievable. +When you upload `reports/q1.pdf` for the first time, Fil One creates version `v1`. If you upload a new `reports/q1.pdf` tomorrow, Fil One creates version `v2` and `v1` remains intact. If you delete the object over the S3 API without a version ID, Fil One places a **delete marker** at the current version — the object appears deleted, but all previous versions are still retrievable. -WARNING: DELETING IN THE DASHBOARD REMOVES A VERSION PERMANENTLY. The dashboard -never writes a delete marker. Deleting an object there, one at a time or in bulk, -permanently deletes the specific version on the row you chose; deleting the -current version's row removes that version and leaves the earlier versions as -they are. **Empty bucket** removes every version and delete marker in the bucket. +This behavior applies to all objects in versioned buckets. + +Warning: Deleting in the dashboard removes a version permanently +The dashboard never writes a delete marker. Deleting an object there, one at a time or in bulk, permanently deletes the specific version on the row you chose. Deleting the current version's row removes that version, and the earlier versions are left as they are. **Empty bucket** removes every version and delete marker in the bucket. See [Deleting objects](https://docs.filone.com/app/buckets#deleting-objects). ## Access key permissions for versions -Version-specific operations are separate granular key permissions, none granted -automatically. Select them under the matching base permission: +Version-specific operations are separate granular permissions on an access key, and none of them is granted automatically. When you [create the key](https://docs.filone.com/security/api-keys), select the ones you need under the matching base permission: | To do this | Grant | Under | |------------|-------|-------| -| List object versions (list-object-versions) | List object versions (ListBucketVersions) | List | -| Download a specific version (--version-id on get-object) | Read object versions (GetObjectVersion) | Read | -| Delete a specific version or a delete marker | Delete object versions (DeleteObjectVersion) | Delete | +| List object versions (`list-object-versions`) | **List object versions** (`ListBucketVersions`) | List | +| Download a specific version (`--version-id` on `get-object`) | **Read object versions** (`GetObjectVersion`) | Read | +| Delete a specific version or a delete marker | **Delete object versions** (`DeleteObjectVersion`) | Delete | ## Billing implications -Every version is a full copy of the object and is billed as stored storage. -Uploading and then overwriting 100 files leaves 200 billable object versions -consuming storage. +Every version is a full copy of the object and is billed as stored storage. If you upload and then overwrite 100 files, you have 200 billable object versions consuming storage. Consider cleaning up old versions if storage cost is a concern. See [Pricing](https://docs.filone.com/billing/pricing). ## Listing versions +AWS CLI: ```bash # List all versions in a bucket -aws s3api list-object-versions --bucket my-bucket --profile filone +aws s3api list-object-versions \ + --bucket my-bucket \ + --profile filone # List versions for a specific object aws s3api list-object-versions \ @@ -771,6 +829,7 @@ aws s3api list-object-versions \ --profile filone ``` +Python (boto3): ```python paginator = s3.get_paginator("list_object_versions") for page in paginator.paginate(Bucket="my-bucket", Prefix="reports/q1.pdf"): @@ -782,6 +841,7 @@ for page in paginator.paginate(Bucket="my-bucket", Prefix="reports/q1.pdf"): ## Retrieving a specific version +AWS CLI: ```bash aws s3api get-object \ --bucket my-bucket \ @@ -791,6 +851,7 @@ aws s3api get-object \ --profile filone ``` +Python (boto3): ```python s3.download_file( "my-bucket", @@ -802,17 +863,16 @@ s3.download_file( ## Going back to a previous version -The Fil One dashboard has no restore, roll-back, or "make current" button — you -can list, download, and delete prior versions there, but not promote one to -current. +The Fil One **dashboard** has no restore, roll-back, or "make current" button — you can list, download, and delete prior versions there, but not promote one to current. -Note: promoting a version to current with CopyObject is confirmed working in -us-east-1. This has not yet been confirmed in eu-west-1 — use the -download-and-reupload method there instead. +Info: Region-dependent +Promoting a version to current with `CopyObject` is confirmed working in `us-east-1`. This has not yet been confirmed in `eu-west-1` — use the download-and-reupload method there instead. -In us-east-1, copy the version onto the current key. Use CopyObject with -x-amz-copy-source-version-id to promote an older version to current in place: +### In `us-east-1`: copy the version onto the current key +Use `CopyObject` with `x-amz-copy-source-version-id` to promote an older version to current in place: + +AWS CLI: ```bash aws s3api copy-object \ --bucket my-bucket \ @@ -821,6 +881,7 @@ aws s3api copy-object \ --profile filone ``` +Python (boto3): ```python s3.copy_object( Bucket="my-bucket", @@ -833,12 +894,13 @@ s3.copy_object( ) ``` -This creates a new current version with the old content; the version copied from -stays intact. +This creates a new current version with the old content; the version you copied from stays intact. + +### In `eu-west-1`, or as a universal fallback: download and re-upload -In eu-west-1, or as a universal fallback, download and re-upload. The re-upload -becomes a new current version, and the version copied from stays intact: +To go back to an earlier version without `CopyObject`, download it and upload it again. The re-upload becomes a new current version, and the version you copied from stays intact. +AWS CLI: ```bash aws s3api get-object \ --bucket my-bucket \ @@ -854,6 +916,7 @@ aws s3api put-object \ --profile filone ``` +Python (boto3): ```python old = s3.get_object( Bucket="my-bucket", @@ -868,17 +931,15 @@ s3.put_object( ) ``` -If the current version is a delete marker, the object can instead be made -visible again by deleting that delete marker by its version ID. +If the current version is a delete marker, you can instead make the object visible again by deleting that delete marker by its version ID — see below. ## Delete markers -Deleting an object without specifying a version ID places a delete marker at the -top of the version stack. The object appears deleted in standard listings and -GetObject returns NoSuchKey. Previous versions remain intact and retrievable by -version ID. To permanently delete a specific version (including a delete -marker), specify the version ID: +When you delete an object without specifying a version ID, Fil One places a **delete marker** at the top of the version stack. The object appears deleted in standard listings and `GetObject` returns `NoSuchKey`. The previous versions remain intact and can be retrieved by version ID. +To permanently delete a specific version (including a delete marker), specify the version ID in the delete request: + +AWS CLI: ```bash # Delete a specific version permanently aws s3api delete-object \ @@ -895,7 +956,9 @@ aws s3api delete-object \ --profile filone ``` +Python (boto3): ```python +# Delete a specific version permanently s3.delete_object( Bucket="my-bucket", Key="reports/q1.pdf", @@ -903,24 +966,22 @@ s3.delete_object( ) ``` -Note: permanently deleting a version cannot be undone. If the version has an -active Object Lock Compliance retention, the delete request is rejected. +Warning: +Permanently deleting a version cannot be undone. If the version has an active Object Lock Compliance retention, the delete request will be rejected. ## Versioning and Object Lock -Object Lock is configured on the bucket, when the bucket is created, and -requires versioning on the same bucket. Neither can be turned on later. -Retention is then tracked per version: the bucket's default retention is applied -to each new object version as it is uploaded, and each version carries its own -retention independently. In practice: +Object Lock is configured on the **bucket**, when the bucket is created. You enable it there and set a default retention mode and duration, and Object Lock requires versioning to be enabled on the same bucket. Neither can be turned on later. -- A version under active Compliance retention cannot be deleted, regardless of - whether a delete marker exists above it. -- A delete marker is not itself protected by retention, so an object can appear - deleted while its underlying versions remain locked and intact. -- Because retention comes from the bucket default, a bucket with a long default - retention accumulates locked versions on every overwrite. Each is billed as - stored storage and cannot be removed until its retention expires. +Retention is then tracked per **version**. The bucket's default retention is applied to each new object version as it is uploaded, and each version carries its own retention independently — locking one version does not affect the versions above or below it, and older versions keep their own settings. + +What that means in practice: + +- You cannot delete a version that is under active Compliance retention, regardless of whether a delete marker exists above it. +- A delete marker is not itself protected by retention, so an object can still appear deleted while its underlying versions remain locked and intact. +- Because retention comes from the bucket default, a bucket with a long default retention will accumulate locked versions on every overwrite. Each one is billed as stored storage and cannot be removed until its retention expires. + +See [Object Lock](https://docs.filone.com/storage/object-lock) for modes, durations, and examples. --- @@ -929,202 +990,164 @@ retention independently. In practice: Source: https://docs.filone.com/storage/object-lock -Object Lock enforces Write-Once-Read-Many (WORM) protection. Depending on the -mode, a locked object cannot be deleted or overwritten until its retention -period expires — in Compliance mode, not even by the account owner. Whether it -satisfies a specific regulation is for your own compliance review to decide. +Object Lock lets you enforce Write-Once-Read-Many (WORM) protection on stored objects. Depending on the mode you choose, a locked object cannot be deleted or overwritten until its retention period expires — in **Compliance** mode, not even by the organization Owner. This is designed for data-retention, legal-preservation, and ransomware-protection use cases. Whether it satisfies a specific regulation is for your own compliance review to decide — see [On regulatory compliance](#on-regulatory-compliance) at the end of this page. ## Key concepts -- Retention period — a duration during which an object version cannot be deleted - or overwritten. -- Compliance mode — the strictest protection. No user, including the account - owner, can shorten the retention period or delete a locked object before it - expires. -- Governance mode — a softer protection. In standard S3, a caller holding a - special bypass permission can override Governance retention and delete objects - early. Fil One does NOT currently expose a grantable bypass permission, so in - practice a Governance-locked object is protected for its retention period the - same way a Compliance one is; the difference is that Governance is not - positioned as an absolute, unbypassable guarantee at the platform level. -- Versioning — Object Lock requires versioning, so both are enabled when - creating the bucket. Versioning cannot be suspended once set. +**Retention period** — A duration during which an object version cannot be deleted or overwritten. + +**Compliance mode** — The strictest protection. No user, including the organization Owner, can shorten the retention period or delete a locked object before it expires. + +**Governance mode** — A softer protection. In standard S3, a caller holding a special *bypass* permission can override Governance retention and delete objects early. **Fil One does not currently expose a grantable bypass permission**, so in practice a Governance-locked object is protected for its retention period the same way a Compliance one is; the difference is that Governance is not positioned as an absolute, unbypassable guarantee at the platform level. + +**Versioning** — Object Lock requires versioning, so you enable both when creating the bucket. Versioning cannot be suspended on any Fil One bucket once it is set. ## Enabling Object Lock -Object Lock is opt-in and must be enabled at bucket creation time. It cannot be -added to an existing bucket, and once enabled it cannot be disabled. +Object Lock is **opt-in** and must be enabled at **bucket creation time**. It cannot be added to an existing bucket, and once enabled it cannot be disabled. -1. From the dashboard, click **New bucket**, then **Create bucket**. -2. Enter a bucket name. -3. Enable **Versioning**. -4. Enable **Object Lock**. -5. Select a retention mode: **Governance** (the default) or **Compliance**. -6. Set a default retention duration — from 1 day up to 100 years (36,500 days). +To create a bucket with Object Lock: + +1. From the dashboard, click **New bucket** to open the create form. +2. Enter a bucket name and choose a region. +3. Expand **Advanced settings** and turn on **Versioning**. Until you do, Object Lock shows a **Needs Versioning** badge. +4. Turn on **Object Lock**. +5. Turn on **Retention** and select a mode: **Governance** (the default) or **Compliance**. +6. Set a default retention duration, from 1 day up to 100 years (36,500 days). It starts at 15 days. 7. Click **Create bucket**. +Warning: +Object Lock must be enabled at bucket creation. It cannot be added to an existing bucket. + ## Retention modes | Mode | Can it be overridden early? | Typical use | |------|-----------------------------|-------------| -| Governance (default) | Not through any Fil One-granted permission today | Internal-policy retention, audit-friendly workflows | -| Compliance | No — not by anyone, including account owners | Strict, long-term immutable record-keeping | - -In Compliance mode the retention period is absolute; no action can shorten or -remove it once set. In Governance mode, standard S3 allows a caller with the -bypass permission to delete locked objects early, but Fil One does not currently -expose that permission, so today a Governance lock behaves like a firm retention -lock rather than a routinely-overridable one. - -Note: choose the retention mode carefully at bucket creation — it is fixed for -the life of the bucket. There is no update-bucket operation, so a Governance -bucket cannot be converted into a Compliance one later. Moving objects into a -bucket with a different mode means copying them into it with CopyObject over the -S3 API or downloading and re-uploading them. Compliance retention periods, once -set, cannot be shortened or removed. +| **Governance** (default) | Not through any Fil One-granted permission today | Internal-policy retention, audit-friendly workflows | +| **Compliance** | No — not by anyone, including organization Owners | Strict, long-term immutable record-keeping | + +In **Compliance mode**, the retention period is absolute. No action can shorten or remove it once set. + +In **Governance mode**, standard S3 allows a caller with the bypass permission to delete locked objects early. Fil One does not currently expose that permission, so today a Governance lock behaves like a firm retention lock rather than a routinely-overridable one. Choose it when you want WORM-style protection without positioning it as an absolute regulatory guarantee. + +Warning: +Choose your retention mode carefully **at bucket creation** — it is fixed for the life of the bucket and cannot be changed afterwards. There is no update-bucket operation, so you cannot convert a Governance bucket into a Compliance one later. Moving objects into a bucket with a different mode means copying them into it with `CopyObject` over the S3 API (see [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility)) or downloading and re-uploading them. Compliance retention periods, once set, cannot be shortened or removed. ## Setting per-object retention -The default retention period set at bucket creation is applied automatically to -every object uploaded to that bucket. +The default retention period set at bucket creation is applied automatically to every object uploaded to that bucket. -Note: PutObjectRetention needs a granted permission. Setting or changing -retention on an individual object version via PutObjectRetention works in BOTH -REGIONS, but only with the matching granular access-key permission, which is -never granted automatically. Extending a retention period is straightforward. -Shortening one uses the standard S3 bypass-governance-retention mechanism (a -protocol-level capability of the gateway, NOT a permission Fil One's own access -keys can grant). +Info: `PutObjectRetention` needs a granted permission +Setting or extending retention on an *individual* object version via `PutObjectRetention` works in **both regions**, but only with the **Set retention** permission, which is never granted automatically and only an organization Owner can grant. Retention can be extended but not shortened: no Fil One access key can be granted the bypass-governance permission. See [Key concepts](#key-concepts). -Object Lock buckets are always versioned, so a retention call should target a -specific version with --version-id; without it the call targets whatever the -current version is (possibly a delete marker). +Object Lock buckets are always versioned, so a retention call should target a specific version with `--version-id`; without it the call targets whatever the current version is (possibly a delete marker). +The examples use Governance mode. Replace `YYYY-MM-DD` with a date a day or two from now while you're testing: you can extend retention later, but on Fil One you can't shorten it in either mode, because no key can be granted the bypass permission. + +Danger: Compliance retention can't be shortened or removed +If you set `"Mode": "COMPLIANCE"`, nobody, including the organization Owner, can delete that version or shorten its retention until the date passes. The data keeps being billed until then, up to 100 years. + +AWS CLI: ```bash aws s3api put-object-retention \ - --bucket my-compliance-bucket \ + --bucket my-bucket \ --key important-record.pdf \ --version-id YOUR_VERSION_ID \ - --retention '{"Mode": "COMPLIANCE", "RetainUntilDate": "2027-12-31T00:00:00Z"}' \ - --endpoint-url https://s3.us-east-1.filonecontent.com + --retention '{"Mode": "GOVERNANCE", "RetainUntilDate": "YYYY-MM-DDT00:00:00Z"}' \ + --endpoint-url https://s3.us-east-1.filonecontent.com \ + --region us-east-1 ``` - +Python (boto3): ```python s3.put_object_retention( - Bucket="my-compliance-bucket", + Bucket="my-bucket", Key="important-record.pdf", VersionId="YOUR_VERSION_ID", Retention={ - "Mode": "COMPLIANCE", - "RetainUntilDate": "2027-12-31T00:00:00Z", + "Mode": "GOVERNANCE", + "RetainUntilDate": "YYYY-MM-DDT00:00:00Z", }, ) ``` -In standard S3, retention can be extended but never shortened: RetainUntilDate -can move further into the future but not closer, and shortening a Compliance -retention period is rejected with 403 AccessDenied. Fil One's us-east-1 gateway -has been confirmed to follow this; eu-west-1 has not yet been independently -verified. +In standard S3, retention can be extended but never shortened: you can move `RetainUntilDate` further into the future but not closer, and shortening a Compliance retention period is rejected (with `403 AccessDenied`). Fil One's `us-east-1` gateway has been confirmed to follow this; `eu-west-1` has not yet been independently verified. ## Checking retention status -The object detail page in the dashboard shows an object's retention status and -displays a lock banner for Compliance-locked objects. GetObjectRetention is also -available over the S3 API: +The object detail page in the dashboard shows an object's retention status, and displays a lock banner for Compliance-locked objects — so you don't need the CLI just to check. `GetObjectRetention` is also available over the S3 API: ```bash aws s3api get-object-retention \ - --bucket my-compliance-bucket \ + --bucket my-bucket \ --key important-record.pdf \ - --endpoint-url https://s3.us-east-1.filonecontent.com + --version-id YOUR_VERSION_ID \ + --endpoint-url https://s3.us-east-1.filonecontent.com \ + --region us-east-1 +``` + +Returns: + +```json +{ + "Retention": { + "Mode": "GOVERNANCE", + "RetainUntilDate": "YYYY-MM-DDT00:00:00+00:00" + } +} ``` ## Deleting locked objects -Attempting to delete an object with active retention returns 403 AccessDenied. -On a versioned bucket, a DELETE without a version ID places a delete marker: the -object appears deleted to applications, but the underlying version remains -protected and intact until retention expires. +Attempting to delete an object with active retention returns `403 AccessDenied`. + +On a versioned bucket, a `DELETE` request without a version ID places a delete marker. The object appears deleted to applications, but the underlying version remains protected and intact until retention expires. ## Deleting buckets with locked objects -A bucket can only be deleted once it is empty, and objects under active -retention cannot be deleted, so a bucket holding locked versions cannot be -removed until their retention expires and you delete them. **Empty bucket** in -the dashboard reports locked objects as ones it could not delete and leaves them -in place. +A bucket can only be deleted once it is empty, and objects under active retention cannot be deleted, so a bucket holding locked versions cannot be removed until their retention expires and you delete them. **Empty bucket** in the dashboard reports locked objects as ones it could not delete and leaves them in place. -Once the bucket is empty, delete it from the dashboard in either region (Owner -and Admin roles only), or over the S3 API with DeleteBucket in us-east-1. -DeleteBucket is not available over the S3 API in eu-west-1. +Once the bucket is empty, delete it from the dashboard in either region (Owner and Admin roles only), or over the S3 API with `DeleteBucket` in `us-east-1`. `DeleteBucket` is not available over the S3 API in `eu-west-1`. See [Buckets](https://docs.filone.com/storage/buckets#deleting-a-bucket). ## Object Lock and API keys -GetBucketVersioning and GetBucketObjectLockConfiguration are selectable -permissions granted when creating a key — they are not included automatically. -Beyond that: +`GetBucketVersioning` and `GetBucketObjectLockConfiguration` are pre-selected when you create a key. Untick them if the key shouldn't read a bucket's versioning or Object Lock settings. Beyond that: -- A key with Delete permission can delete objects in Governance mode buckets - once retention has expired. Fil One does not expose a bypass permission for - deleting before expiry. -- Compliance mode cannot be overridden by any key, regardless of permissions. -- To set retention on an individual version, grant the PutObjectRetention - granular permission — available in BOTH REGIONS, never granted automatically. +- A key with **Delete** permission can delete objects in **Governance** mode buckets once retention has expired. Fil One does not expose a bypass permission for deleting *before* expiry. +- **Compliance** mode cannot be overridden by any key, regardless of permissions. +- To set retention on an individual version, grant the **Set retention** permission (Owner-only to grant). See the [note above](#setting-per-object-retention). It is available in both regions and is never granted automatically. ## Object Lock during trial -Object Lock is fully available during the free trial, with no trial-specific -retention cap. Trial and paid accounts alike can set retention from 1 day to 100 -years (36,500 days). +Object Lock is fully available during the free trial, with no trial-specific retention cap. Trial and paid accounts alike can set retention periods from **1 day to 100 years** (36,500 days). -Note: a trial lock cannot be undone. Retention outlives the trial — a lock set -during the trial still applies after it ends, and Compliance retention cannot be -shortened once set. Because durations run up to 100 years, an object -Compliance-locked while testing keeps occupying storage (and generating storage -cost once on a paid plan) for the entire retention period, with no way to delete -it early. Use short durations while evaluating. +Warning: A trial lock cannot be undone +Retention outlives the trial: a lock you set during the trial still applies after it ends, and Compliance retention cannot be shortened once set. Because durations run up to 100 years, an object you Compliance-lock while testing keeps occupying storage — and generating storage cost once you are on a paid plan — for the entire retention period, with no way to delete it early. Use short durations while evaluating. ## Object Lock and the Filecoin storage model -When an object is deleted after its retention period expires, it is immediately -removed from the Fil One account and inaccessible via the API and dashboard. -Because Filecoin stores data in sealed sectors, the underlying storage may -persist for a bounded period until the sector naturally expires; the exact -duration is set by the storage layer rather than measured by Fil One. That -residual data stays encrypted, and key custody sits with the regional storage -operator rather than with the customer or Fil One. +When you delete an object after its retention period expires, it is immediately removed from your Fil One account and inaccessible via the API and dashboard. Because Filecoin stores data in sealed sectors, the underlying storage may persist for a bounded period until the sector naturally expires; the exact duration is set by the storage layer rather than measured by Fil One. That residual data stays encrypted, and key custody sits with the regional storage operator rather than with you or Fil One — see [Encryption](https://docs.filone.com/security/encryption). Whether that bounded persistence matters for a particular regulatory obligation is a question for your own compliance review — this documentation does not make that determination. ## Common use cases -Object Lock provides WORM-style retention. These describe the use case, not a -claim that Fil One is certified for the named regulation: +Object Lock provides WORM-style retention. These are common scenarios where teams reach for that capability — they describe the use case, not a claim that Fil One is certified for the named regulation (see the note below): | Use case | Typical retention | What Object Lock provides | |----------|-------------------|---------------------------| -| Financial records | 6-7 years | Immutable, non-rewritable storage for the retention period | -| Healthcare records | 6-10 years | Prevents deletion or overwrite of records under retention | -| Ransomware-resistant backup | 30-90 days | Backups cannot be encrypted-over or deleted while locked | -| Legal preservation | Variable | Retention-based preservation of evidence, or S3 Legal Hold | +| Financial records | 6–7 years | Immutable, non-rewritable storage for the retention period | +| Healthcare records | 6–10 years | Prevents deletion or overwrite of records under retention | +| Ransomware-resistant backup | 30–90 days | Backups cannot be encrypted-over or deleted while locked | +| Legal preservation | Variable | Retention-based preservation of evidence, or S3 *Legal Hold* | | Audit-log retention | Varies | Keeps logs unmodified for a fixed window | ## On regulatory compliance -Object Lock provides WORM-style retention, a building block many regulatory -regimes call for. However: +Object Lock provides WORM-style retention, which is a building block many regulatory regimes call for. However: -- Fil One holds NO third-party compliance attestation (for example, an SEC - 17a-4 assessment) for this feature. -- Retention enforcement at the storage gateway is confirmed in both regions, but - by different means: us-east-1 by an automated compatibility suite, eu-west-1 by - engineering testing rather than that suite. If a specific obligation depends on - it, validate the exact behaviour you need. -- The product surfaces NO per-object cryptographic proof (no CID, deal ID, or - seal state) that could be presented to an auditor to demonstrate integrity. +- Fil One holds **no third-party compliance attestation** (for example, an SEC 17a-4 assessment) for this feature. +- Retention enforcement at the storage gateway is confirmed in both regions, but by different means: `us-east-1` by an automated compatibility suite, `eu-west-1` by engineering testing rather than that suite. If a specific obligation depends on it, validate the exact behaviour you need. +- The product surfaces **no per-object cryptographic proof** (no CID, deal ID, or seal state) that you could present to an auditor to demonstrate integrity. -Treat the regulations named above as illustrative use cases, and evaluate -whether Object Lock meets a specific obligation as part of your own compliance -process. +Treat the regulations named above as illustrative use cases, and evaluate whether Object Lock meets a specific obligation as part of your own compliance process. --- @@ -1133,63 +1156,74 @@ process. Source: https://docs.filone.com/security/account-security -Covers securing the account you sign in with. API request authentication is a -separate mechanism (see Authentication / API Keys). +This page covers securing the account you sign in with. For authenticating **API requests**, which is a separate mechanism, see [Authentication](https://docs.filone.com/security/authentication) and [API Keys](https://docs.filone.com/security/api-keys). ## Signing in -Four methods: passkeys (the primary method), Google, GitHub, and email with -password. A new account must verify its email address before the dashboard -opens; until then every page redirects to a verification screen. +Fil One supports four sign-in methods: + +- **Passkeys**, the primary method +- **Google** +- **GitHub** +- **Email with password** + +A new account must verify its email address before the dashboard opens. Until you do, every page redirects to a verification screen. ## Two-factor authentication -Opt-in per user, managed from Settings > Security. Three factor types: +Two-factor authentication is opt-in per user and managed from **Settings**, under **Security**. Three factor types are supported: + +| Factor | Shown in the dashboard as | What it is | +|--------|---------------------------|------------| +| Authenticator app | **Authenticator app (OTP)** | A time-based one-time code from an app such as 1Password, Authy, or Google Authenticator | +| Security key | **Security key** | A roaming WebAuthn authenticator, for example a YubiKey | +| Device biometrics | **Device biometrics** | A platform WebAuthn authenticator: Face ID, Touch ID, or Windows Hello | -| Factor | Dashboard label | What it is | -|--------|-----------------|------------| -| Authenticator app | Authenticator app (OTP) | Time-based one-time code from an app (1Password, Authy, Google Authenticator) | -| Security key | Security key | Roaming WebAuthn authenticator, e.g. a YubiKey | -| Device biometrics | Device biometrics | Platform WebAuthn authenticator: Face ID, Touch ID, Windows Hello | +**SMS and email codes are deliberately not offered.** Both are vulnerable to SIM-swap and mailbox-compromise attacks, so Fil One only supports factors bound to a device or an app. -SMS and email codes are DELIBERATELY NOT OFFERED (SIM-swap and -mailbox-compromise risk). Only device- or app-bound factors are supported. More -than one factor can be enrolled, and individual ones removed. Signing in with a -passkey counts as a strong factor, so no second factor is asked for on top of it. +You can enrol more than one factor and remove individual ones from Settings. + +Signing in with a passkey counts as a strong factor, so you aren't asked for a second factor on top of it. ## Passkeys -Listed separately from two-factor methods, under Settings > Passkeys. With none -enrolled, the dashboard prompts to add one on next sign-in. Limit is 20 passkeys -per account. Accounts that sign in with Google or GitHub don't see the Passkeys -section. +Passkeys are listed separately from two-factor methods in Settings, under **Passkeys**. If you have none enrolled, the dashboard prompts you to add one on your next sign-in. + +You can hold up to **20 passkeys** on one account, which is enough to cover several devices without having to retire an old one to add a new one. + +Accounts that sign in with Google or GitHub don't see the **Passkeys** section. ## Recovery codes -A single-use code for signing in after losing access to an authenticator. -Generate or replace from Settings > Security > Recovery code > Regenerate. -Generating a new code invalidates the previous one. +A recovery code is a single-use code for signing in if you lose access to your authenticator. Generate or replace one from **Settings** → **Security** → **Recovery code** → **Regenerate**. + +Generating a new code invalidates the previous one, so store the new value somewhere durable before you close the dialog. -## Step-up re-authentication +Signing in with a recovery code assumes you've lost your device, so the same sign-in asks you to set up a new two-factor method before you reach the console. Have an authenticator app or a passkey ready. -Four actions require a session that was signed in with two-factor -authentication or a passkey, even within an already signed-in session: removing -a two-factor method, removing all two-factor methods, removing a passkey, and -regenerating a recovery code. If the current session wasn't, the dashboard sends -you back through sign-in to step up first, so a session signed in with a password -alone cannot strip the account's protections. +## Changes to security settings require re-authentication -Transferring ownership of an organization has a stricter check: you must have -signed in within the last five minutes, and if you have two-factor authentication -set up, that sign-in must include it or use a passkey. Otherwise the dashboard -sends you back through sign-in first. +Four actions require a session that was signed in with two-factor authentication or a passkey, even inside an already signed-in session: + +- Removing a two-factor method +- Removing all two-factor methods +- Removing a passkey +- Regenerating a recovery code + +If your current session wasn't, the dashboard sends you back through sign-in to step up before the action proceeds. This means a session signed in with a password alone cannot strip the account's protections. + +Transferring ownership of an organization has a stricter check: you must have signed in within the last five minutes, and if you have two-factor authentication set up, that sign-in must include it or use a passkey. Otherwise the dashboard sends you back through sign-in first. ## Changing your password -Settings > Security > Password > Change sends a password-reset email to the -registered address. Google or GitHub sign-ins have no Fil One password to change: -Settings shows the password as Managed by Google (or GitHub), with a link to -update it with that provider. +Change your account password from **Settings** → **Security** → **Password** → **Change**. This sends a password-reset email to your registered address. + +If you sign in with Google or GitHub, there is no password to change in Fil One. **Settings** shows the password as **Managed by Google** (or **GitHub**), with a link to update it with that provider. + +## Related + +- [Authentication](https://docs.filone.com/security/authentication): signing API requests with SigV4 +- [API Keys](https://docs.filone.com/security/api-keys): creating and scoping keys for programmatic access --- @@ -1198,63 +1232,87 @@ update it with that provider. Source: https://docs.filone.com/security/authentication -All API requests to Fil One must be authenticated using AWS Signature Version 4 -(SigV4). Any S3-compatible SDK or tool handles this automatically. +All API requests to Fil One must be authenticated using AWS Signature Version 4 (SigV4). This is the same authentication method used by AWS S3, so any S3-compatible SDK or tool handles it automatically. + +Note: Looking for account sign-in? +This page is about signing **API requests**. For the account you log into the dashboard with, including two-factor authentication, passkeys, and recovery codes, see [Account Security](https://docs.filone.com/security/account-security). + +Note: Keys and endpoints are region-specific +Every access key belongs to a **single region**, chosen when you create it, and it only authenticates requests to that region's endpoint. Examples below use `eu-west-1`, the default region — for `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and region `us-east-1`. If you store data in both regions you need a key for each. ## API keys -| Component | Description | -|-----------|-------------| -| Access Key ID | Identifies your account. Included in request headers. Format: FHXXXXXXXXXXXXXXXX | -| Secret Access Key | Signs your requests. Never sent over the wire. | +Each API key consists of two parts: + +| Component | Description | Example format | +|-----------|-------------|----------------| +| **Access Key ID** | Identifies the key. Included in request headers. | `FHXXXXXXXXXXXXXXXX` | +| **Secret Access Key** | Signs your requests. Never sent over the wire. | `EXAMPLEfakeSECRETkeyDoNotUse...` | + +Your secret key is displayed **once** at creation time. Store it securely. If you lose it, [rotate the key](https://docs.filone.com/security/api-keys#rotating-a-key) to get a new key pair. + +## Creating an API key + +Create keys in the console under **API Keys** → **Create new key**. Pick the **Region** carefully: a key only authenticates against its own region's endpoint, and a key created in the wrong region fails with `403`, the most common first-run mistake. See [Creating an API key](https://docs.filone.com/security/api-keys#creating-an-api-key) for the steps and what each permission allows. + +You can create multiple API keys per account. A key can only carry permissions your role in the organization holds, and Read only members cannot create keys. See [API Keys](https://docs.filone.com/security/api-keys) for details on configuring key permissions. -Your secret key is displayed once at creation time. If you lose it, rotate the -key (see API Keys) to get a new key pair. +## Revoking an API key -You can create multiple API keys per account. A key can only carry permissions -your role in the organization holds, and Read only members cannot create keys. +Go to **API Keys** in the left menu, find the key, open its **⋯** action menu, and choose **Delete**. Deletion is forwarded to the regional storage operator; the key stops working once that change propagates, so rotate any dependent credentials rather than assuming an exact cut-off instant. ## Configuring your client ### AWS CLI +Use **AWS CLI v2**, version 2.13 or later, which reads `endpoint_url` from the profile. Configure credentials into a named `filone` profile (not the default), so they land where `--profile filone` will read them: + ```bash -aws configure -# AWS Access Key ID: YOUR_ACCESS_KEY -# AWS Secret Access Key: YOUR_SECRET_KEY -# Default region name: eu-west-1 +aws configure --profile filone ``` -Named profile (recommended): +When prompted, enter your Access Key ID, Secret Access Key, and `eu-west-1` as the region. Then add the endpoint and path-style setting to the same profile: ```ini -# ~/.aws/config (AWS CLI v2 — v1 ignores endpoint_url) +# ~/.aws/config [profile filone] endpoint_url = https://s3.eu-west-1.filonecontent.com region = eu-west-1 s3 = addressing_style = path - -# ~/.aws/credentials -[filone] -aws_access_key_id = YOUR_ACCESS_KEY -aws_secret_access_key = YOUR_SECRET_KEY ``` +Then use `--profile filone` on your commands. Path-style addressing is required — without it the CLI uses virtual-hosted URLs that fail against Fil One. + ### Python (boto3) +Load credentials from the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables (recommended), which boto3 reads automatically. They're also the names the console's **Download .env** writes. Set `region_name` (SigV4 needs a signing region), path-style addressing, and SigV4 for presigned URLs: + +```python +import boto3 +from botocore.config import Config + +s3 = boto3.client( + "s3", + endpoint_url="https://s3.eu-west-1.filonecontent.com", + region_name="eu-west-1", + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), +) +``` + +For a quick local test only, you can pass credentials inline — never commit this to source control: + ```python import boto3 -import os from botocore.config import Config s3 = boto3.client( "s3", endpoint_url="https://s3.eu-west-1.filonecontent.com", - aws_access_key_id=os.environ["FIL_ACCESS_KEY"], - aws_secret_access_key=os.environ["FIL_SECRET_KEY"], + aws_access_key_id="YOUR_ACCESS_KEY", + aws_secret_access_key="YOUR_SECRET_KEY", region_name="eu-west-1", - config=Config(s3={"addressing_style": "path"}), # required + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) ``` @@ -1267,24 +1325,34 @@ const client = new S3Client({ endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", forcePathStyle: true, - credentials: { - accessKeyId: process.env.FIL_ACCESS_KEY, - secretAccessKey: process.env.FIL_SECRET_KEY, - }, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", + // Credentials come from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY }); ``` ### Go ```go +package main + +import ( + "os" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/s3" +) + func newClient() *s3.Client { return s3.New(s3.Options{ BaseEndpoint: aws.String("https://s3.eu-west-1.filonecontent.com"), Region: "eu-west-1", UsePathStyle: true, Credentials: credentials.NewStaticCredentialsProvider( - os.Getenv("FIL_ACCESS_KEY"), - os.Getenv("FIL_SECRET_KEY"), + os.Getenv("AWS_ACCESS_KEY_ID"), + os.Getenv("AWS_SECRET_ACCESS_KEY"), "", ), }) @@ -1293,12 +1361,10 @@ func newClient() *s3.Client { ## Security best practices -- Do not hardcode credentials in source code. Use environment variables or a - secrets manager. -- Create separate keys for different environments. -- Rotate keys periodically: use Rotate in the key's ⋯ menu, then deploy the new - credentials. The old secret stops working as soon as the new one is issued. -- Revoke keys immediately if compromised. +- **Do not hardcode credentials** in source code. Use environment variables, a secrets manager, or credential files. +- **Create separate keys** for different environments (development, staging, production). +- **Rotate keys periodically.** Use **Rotate** in the key's **⋯** menu, then deploy the new credentials. The old secret stops working as soon as the new one is issued. See [Rotating a key](https://docs.filone.com/security/api-keys#rotating-a-key). +- **Revoke keys immediately** if you suspect they have been compromised. --- @@ -1307,144 +1373,201 @@ func newClient() *s3.Client { Source: https://docs.filone.com/security/api-keys -API keys authenticate your requests to the Fil One S3 API. Each key consists of -an Access Key ID (public identifier) and a Secret Access Key (used to sign requests). +API keys authenticate your requests to the Fil One S3 API. Each key consists of an **Access Key ID** (public identifier) and a **Secret Access Key** (used to sign requests). ## Creating an API key -1. Go to **API Keys** in the left menu of the dashboard. -2. Click **Create new key** (opens a dedicated page). -3. Give the key a descriptive name (e.g., production-backend, ci-pipeline). Max 64 chars (letters, numbers, spaces, and `_ - .`); names starting with `filone-console` (any capitalization) are RESERVED. -4. Choose the key's region (pre-set to eu-west-1, fixed for the life of the key) and set permissions and bucket scope. At least one permission is required, and you can only grant permissions your role holds. -5. Optionally set an expiration: Never expires, 30 days, or a Custom date. -6. Click **Create API key**. -7. **Copy the Secret Access Key immediately.** It is shown only once. If you lose it, rotate the key to get a new one. +1. Go to **API Keys** in the left sidebar of the console. +2. Click **Create new key** (this opens a dedicated page). +3. Give the key a descriptive name (e.g., `production-backend`, `ci-pipeline`). Names are limited to 64 characters (letters, numbers, spaces, and `_ - .`), and names starting with `filone-console` (in any capitalization) are reserved. +4. Choose the key's **region** (see [Region scope](#region-scope)). It is pre-set to `eu-west-1`, and it is fixed for the life of the key. +5. Set the key's permissions and bucket scope (see below). **Read**, **Write**, and **List** are pre-selected, along with the two bucket configuration reads. For a read-only key, untick **Write**. At least one permission is required, and you can only grant permissions your role holds (see [Who can create and manage keys](#who-can-create-and-manage-keys)). +6. Optionally set an expiration: **Never expires**, **30 days**, or a **Custom** date. +7. Click **Create API key**. +8. **Copy the Secret Access Key immediately.** It is shown only once. If you lose it, [rotate the key](#rotating-a-key) to get a new one. If you use **Download .env** or **Download .csv**, the file holds the secret in plain text: move it into your secrets store or credential file, delete the download, and never commit it. ## Key permissions +### Object permissions + +Each key can be granted a combination of the following object-level permissions: + | Permission | What it allows | |------------|----------------| -| Read | GetObject (and HeadObject, same underlying permission), ListMultipartUploadParts. In us-east-1, also ListBucket | -| Write | PutObject, AbortMultipartUpload | -| List | ListObjectsV2 / ListBucket, ListBucketMultipartUploads | -| Delete | DeleteObject | +| **Read** | `GetObject` (and `HeadObject`, which uses the same underlying permission), `ListMultipartUploadParts`. In `us-east-1`, also `ListBucket` | +| **Write** | `PutObject`, `AbortMultipartUpload` | +| **List** | `ListObjectsV2` / `ListBucket`, and listing in-progress multipart uploads (`ListBucketMultipartUploads`) | +| **Delete** | `DeleteObject` | -A key with Read and List only suits read-only access (CDN, analytics). A key with Write but not Delete can upload new objects AND OVERWRITE existing ones, but cannot delete them. The Read grant DIFFERS BY REGION: in us-east-1 it also includes ListBucket, so a key with Read but not List can still list object names there; in eu-west-1, Read does not include listing. +You can grant any combination of these permissions. A key with only **Read** and **List** permissions is suitable for read-only access, such as a CDN or analytics pipeline. A key with **Write** but not **Delete** can upload new objects and overwrite existing ones, but cannot delete them. Overwriting replaces an object's data, so on a bucket without [versioning](https://docs.filone.com/storage/versioning) a **Write** key can still destroy data. Use versioning or [Object Lock](https://docs.filone.com/storage/object-lock) if that matters. -Listing your bucket names (ListAllMyBuckets) is granted to every key automatically and is not one of the permissions above. Bucket management permissions (CreateBucket/DeleteBucket) appear on the eu-west-1 create form but are disabled ("Not supported in Europe (France)"). The bucket configuration permissions (GetBucketVersioning/GetBucketObjectLockConfiguration) are selectable in every region, and the console create form PRE-SELECTS both, so untick them if not needed. Governance Object Lock has no grantable bypass permission in the product. PutObjectRetention and PutObjectLegalHold (Set retention / Set legal hold in the console) can only be granted by an OWNER; for other roles the create form doesn't show them. PutObjectRetention and Legal Hold (GetObjectLegalHold/PutObjectLegalHold) are grantable and work in both regions. +The **Read** grant differs by region. In `us-east-1` it also includes `ListBucket`, so a key with **Read** but not **List** can still list object names there. In `eu-west-1`, **Read** does not include listing. -## Who can create and manage keys +Listing the *names* of your buckets (`ListAllMyBuckets`) is granted to every key automatically and is not one of the permissions above. Multipart uploads (`CreateMultipartUpload`, `UploadPart`, `CompleteMultipartUpload`) need **Write**. See [Multipart Uploads](https://docs.filone.com/storage/multipart-uploads). -A key can only carry permissions your organization role holds, and the create form only offers those: +### Bucket management permissions -- Read only members cannot create keys and don't see the key list. -- Members can create keys, and see, rotate, and delete only the keys they created. -- Admins and Owners can create keys and see, rotate, and delete every key in the organization. +These are standalone permissions — they do not require any object permission. They can only be granted in regions where bucket management is available through the S3 API. In `eu-west-1` they appear on the create form but are disabled, with the tooltip **Not supported in Europe (France)**, so they cannot be granted on an `eu-west-1` key. See [Buckets](https://docs.filone.com/storage/buckets). -Keys follow the person who created them. If a member's role is narrowed, any key they created that the new role couldn't create is revoked. Removing a member from the organization revokes the keys they created. +| Permission | What it allows | +|------------|----------------| +| `CreateBucket` | Create a new bucket | +| `DeleteBucket` | Delete an empty bucket | -## Bucket scope +Listing buckets is always permitted and is not a separate, configurable permission. -By default, a key has access to all buckets in your account. You can restrict a -key to specific buckets. This limits the blast radius of a compromised key. +### Bucket configuration permissions -## Key expiration +These read a bucket's settings and are selectable in every region, including `eu-west-1`. The create form in the console pre-selects both, so untick them if your key doesn't need them. -You can set an expiration date when creating a key. After expiration, the key no -longer authenticates and requests fail with a 403 (typically AccessDenied or -InvalidAccessKeyId). Revocation/deletion is forwarded to the regional operator; -treat it as effective quickly rather than at a guaranteed instant. +| Permission | What it allows | +|------------|----------------| +| `GetBucketVersioning` | Read whether versioning is enabled on a bucket | +| `GetBucketObjectLockConfiguration` | Read a bucket's default Object Lock retention policy | -## Viewing and managing keys +### Granular permissions -The API Keys list shows: Name (with the Access Key ID beneath), Region (hidden on -narrow screens), Buckets, Permissions, Created by (who created the key, and who -rotated it and when; shown when the organization has more than one member), -Status (currently ALWAYS "Active"), Last Used (currently ALWAYS "Never"). Status -and Last Used are placeholders, and the list doesn't show a key's expiry date, so -keep your own record of when each key expires. You cannot view the Secret Access -Key after creation. +You can enable additional granular permissions on top of the basic object permissions. Each granular permission requires only its **parent basic permission** — the bucket does **not** need versioning or Object Lock enabled for the permission to be selectable: -## Rotating a key +| Granular permission | Requires basic | What it allows | +|---------------------|----------------|----------------| +| `GetObjectVersion` | Read | Retrieve specific versions of an object | +| `GetObjectRetention` | Read | View retention policy on an object | +| `GetObjectLegalHold` | Read | View legal hold status on an object | +| `PutObjectRetention` | Write | Apply or modify retention policies | +| `PutObjectLegalHold` | Write | Apply or remove legal holds | +| `ListBucketVersions` | List | List all versions of objects in a bucket | +| `DeleteObjectVersion` | Delete | Permanently delete a specific object version | -Rotation gives a key a new Access Key ID and Secret Access Key and keeps -everything else: name, permissions, bucket scope, region, and expiry date. +Granular permissions are additive — a key must have the corresponding basic permission before a granular permission can be granted. For example, `PutObjectRetention` requires the **Write** basic permission. -1. In API Keys, open the key's ⋯ menu and choose **Rotate**. -2. Confirm with **Rotate key** in the **Rotate access key** dialog. -3. Copy or download the new credentials from **Save your credentials**; the - secret is shown only once. +`PutObjectRetention` and `PutObjectLegalHold` (**Set retention** and **Set legal hold** in the console) can only be granted by an Owner. For other roles, the create form doesn't show them. -The old secret stops working as soon as the new one is issued. If the old key -couldn't be revoked, the console says it is still active; delete it yourself. An -EXPIRED key can't be rotated (create a new one). Rotate only appears on keys your -current role could still create. To move an application onto a key with -different permissions or buckets, create the new key, switch over, then delete -the old key. +Note: +Granting `PutObjectRetention` makes the permission available on the key. Per-object retention calls work in both regions. See [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility#object-lock). -## Security best practices +Note: +`GetObjectLegalHold` and `PutObjectLegalHold` can be granted on a key. Legal Hold operations work through the S3 API in both regions. See [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility#object-lock). -- Use separate keys per environment (development, staging, production). -- Use the minimum permissions required. -- Scope keys to specific buckets when possible. -- Set expiration dates on temporary keys. -- Rotate keys periodically: use Rotate on the key, then update your application. -- Revoke immediately if compromised. -- Never hardcode credentials in source code. +## Who can create and manage keys +A key can only carry permissions that your [role](https://docs.filone.com/app/organization#roles-and-permissions) in the organization holds, and the create form only offers those. What each role can do with keys: ---- +- **Read only** members cannot create keys and don't see the key list. +- **Members** can create keys, and see, rotate, and delete only the keys they created. +- **Admins** and **Owners** can create keys and see, rotate, and delete every key in the organization. -# Encryption +Keys follow the person who created them. -Source: https://docs.filone.com/security/encryption +Warning: Membership changes revoke keys +If a member's role is narrowed, any key they created that the new role couldn't create is revoked. Removing a member from the organization revokes every key they created, and so does transferring ownership for keys an Admin can't hold. The revoked keys stop working immediately, and the member is emailed a list of them. Before you change someone's access, move any application that uses their keys onto a new key. -Fil One encrypts all data by default. There is nothing to configure. +## Region scope -## Encryption at rest +Every key belongs to a **single region**, chosen when you create it. A key only authenticates requests to that region's endpoint — it cannot be used against another region, and it cannot be moved to one afterward. If you store data in both `eu-west-1` and `us-east-1`, you need a separate key for each. -All objects are encrypted at rest. Applied automatically on write, decrypted -automatically on read, and it cannot be disabled. Applies to all objects in all -buckets with no exceptions. Encryption is performed by the S3 storage gateway for -the bucket's region, not by the Fil One console. The specific cipher is set by the -regional operator and is not documented here. +The region also determines which permissions are available: the bucket management permissions above cannot be granted on an `eu-west-1` key. -## Encryption in transit +## Bucket scope -All connections to the regional endpoints (https://s3.eu-west-1.filonecontent.com, -https://s3.us-east-1.filonecontent.com) use TLS. HTTP connections are rejected. -Applies to all API operations including uploads, downloads, presigned URLs, -and metadata requests. +By default, a key has access to all buckets in the key's region. You can restrict a key to one or more specific buckets, which limits **object operations** to that set. Note that listing your bucket *names* (`ListAllMyBuckets`) is always permitted, so bucket scoping restricts access to bucket **contents** rather than hiding that other buckets exist. -## Client-side encryption +This is useful when: +- Different services need access to different buckets +- You want to limit the blast radius of a compromised key +- External vendors or partners need access to a specific dataset + +## Key expiration + +You can set an expiration date when creating a key. The key works through the whole of that day (UTC) and stops at the start of the next one. After that, the key no longer authenticates and requests signed with it fail with a `403` (typically `AccessDenied` or `InvalidAccessKeyId`). + +Expiring keys are useful for: +- Temporary access grants +- CI/CD pipelines where you rotate credentials on a schedule +- Short-lived integrations + +## Viewing and managing keys + +Go to **API Keys** in the left sidebar to see your keys. The list shows: + +| Column | Description | +|--------|-------------| +| Name | The label you gave the key at creation, with the Access Key ID shown beneath it | +| Region | The region the key belongs to (hidden on narrow screens) | +| Buckets | Which buckets the key can access (all, or a specific set) | +| Permissions | The object permissions as badges, and a **+***n* badge for the rest | +| Created by | Who created the key, and who rotated it and when. Shown when your organization has more than one member | +| Status | **Active**, or **Expired** once the expiry date has passed | + +Click a key's row to see its expiry date, region, buckets, and full permissions. The console doesn't show when a key was last used, so name keys after what uses them. You cannot view the Secret Access Key after creation. See [API Keys in the console](https://docs.filone.com/app/api-keys#the-key-list) for search, filters, and deleting several keys at once. + +## Rotating a key + +Rotation gives a key a new Access Key ID and Secret Access Key and keeps everything else: its name, permissions, bucket scope, region, and expiry date. + +1. Find the key in **API Keys**, open its **⋯** action menu, and choose **Rotate**. +2. Confirm with **Rotate key** in the **Rotate access key** dialog. +3. Copy or download the new credentials from the **Save your credentials** dialog. As at creation, the secret is shown only once. + +The old secret stops working as soon as the new one is issued, so update your applications right away. If the old key couldn't be revoked, the console tells you it is still active; delete it from the list yourself. + +You can't rotate an expired key; create a new one instead. **Rotate** only appears on keys your current role could still create. -Optional. If your requirements call for client-side encryption, encrypt the bytes -in your own application before uploading. AWS's S3 Encryption Client exists only -for some SDKs (Java, .NET, Go, Ruby) — NOT boto3, the AWS CLI, or JS v3 — so with -those you supply your own crypto. Fil One stores whatever bytes you send. -Client-side encryption is in addition to the server-side encryption that Fil One -applies automatically. +To move an application onto a key with different permissions or buckets, create the new key, switch the application over, then delete the old key. + +## Revoking a key + +Find the key in **API Keys**, open its **⋯** action menu, and choose **Delete**. A deleted key can't be restored. Anything that uses it loses access, so switch your applications to another key first. The key stays in your list until its revocation is confirmed. Treat revocation as taking effect quickly rather than at a guaranteed instant. + +## Security best practices + +- **Use separate keys per environment.** Create different keys for development, staging, and production. This limits the impact if a key is leaked. +- **Use the minimum permissions required.** A key that only needs to read objects should not have Write or Delete permissions. +- **Scope keys to specific buckets** when possible, especially for external integrations. +- **Set expiration dates** on keys that are only needed temporarily. +- **Rotate keys periodically.** Use **Rotate** on the key, then update your application with the new credentials. See [Rotating a key](#rotating-a-key). +- **Revoke keys immediately** if you suspect compromise, and rotate anything that depended on them. Treat revocation as effective quickly rather than assuming a precise cut-off instant. +- **Never hardcode credentials** in source code. Use environment variables or a secrets manager, and keep downloaded `.env` and `.csv` credential files out of version control. +- **Don't paste keys into AI tools.** Give a coding agent its own narrowly scoped key in a named profile instead. + +See [Authentication](https://docs.filone.com/security/authentication) for how to configure your S3 client with your API keys. --- -# Pricing +# Encryption -Source: https://docs.filone.com/billing/pricing +Source: https://docs.filone.com/security/encryption -Fil One is priced at **$5.99 / TB / month**, with a **$5.99 / month minimum**. If you store less than 1 TB, you are billed the $5.99 minimum. +Fil One encrypts all data by default. There is nothing to configure — encryption is always on. -No egress fees, no per-request charges, no hidden costs. +## Encryption at rest -This is the self-service **Pay as you go** plan. For volume pricing on 1, 3, or 5-year terms, the **Business plan** is arranged with the sales team. +All objects stored in Fil One are encrypted at rest. Encryption is applied automatically when data is written and decrypted automatically when data is read. You do not need to set any headers or configure any options, and it cannot be disabled. -## How billing is calculated +Encryption is performed by the S3 storage gateway for the region your bucket lives in, not by the Fil One console. This applies to all objects in all buckets, with no exceptions. + +**Do not send encryption headers.** Fil One applies its own server-side encryption, and you cannot request a specific mode. Uploads specifying `ServerSideEncryption: aws:kms` (SSE-KMS) are **rejected in both regions**: with `InvalidRequest` in `us-east-1`, and with `AccessDenied` or `InvalidRequest` in `eu-west-1` depending on the operation (`PutObject`, `CopyObject`, and `CreateMultipartUpload` are all affected). SSE-C headers are rejected in `eu-west-1`; this is not yet confirmed in `us-east-1`, so don't send them there either. Omit encryption headers entirely: encryption is applied either way. + +The bucket-level encryption operations (`GetBucketEncryption`, `PutBucketEncryption`, `DeleteBucketEncryption`) can't be granted to any access key, in either region, so there is no encryption configuration to read or change over the API. Encryption is still always on. + +## Encryption in transit + +All connections to the regional endpoints (`https://s3.eu-west-1.filonecontent.com`, `https://s3.us-east-1.filonecontent.com`) use **TLS**. HTTP connections are rejected. Your data is always encrypted during transmission between your application and the Fil One endpoint. + +This applies to all API operations, including uploads, downloads, presigned URLs, and metadata requests. -Your bill is based on the average amount of data you store over the billing period. Stored bytes are measured as daily readings and averaged across the billing period; a metering job reports the running average twice a day (~07:00 and 19:00 UTC). Storage is charged at a single flat rate of $5.99 per TB per month with a $5.99/month minimum — there is no separate "first TB" tier, just one linear rate plus a floor. Storage is measured in decimal units (1 TB = 1,000 GB). +## Key management -Illustrative figures (steady amount stored for the full month, at $5.99/TB with the $5.99 minimum applied): 500 GB ≈ $5.99 (minimum applies); 1 TB (1,000 GB) ≈ $5.99; 1.5 TB ≈ $8.99; 2 TB ≈ $11.98. These are illustrative — your invoice on the Billing page is the source of truth for exact amounts. Storage that changes during the month is averaged first. +Encryption keys are held by the **regional storage operator** that fulfils storage for your bucket's region, not by Fil One and not by you. You do not supply or manage encryption keys, and there is no customer-managed-key option. -These are the prices for new customers. Organizations that subscribed before the move to $5.99 keep their earlier terms: $4.99 / TB / month with a $4.99 / month minimum, or, for accounts created before any monthly minimum was introduced, per-unit pricing with no minimum. The Billing page shows your own rate. +If your compliance requirements depend on the specific cipher in use, or on who holds key material for a given region, [contact support](https://docs.filone.com/app/support) — those details are set by the regional operator rather than by Fil One. + +## Client-side encryption + +If your security requirements call for client-side encryption (encrypting data before it reaches the network), encrypt the bytes in your own application before uploading. Note that AWS's dedicated **S3 Encryption Client** exists only for some SDKs (Java, .NET, Go, Ruby) — **boto3, the AWS CLI, and the JavaScript SDK v3 do not provide one** — so with Python, the CLI, or JavaScript you must handle encryption yourself with a standard crypto library. Fil One stores whatever bytes you send: if you encrypt client-side, the stored object is the encrypted blob. + +Client-side encryption is optional and is in addition to the server-side encryption that Fil One applies automatically. --- @@ -1455,43 +1578,128 @@ Source: https://docs.filone.com/billing/trial ## Free trial -Every new account starts with a 30-day free trial. No credit card required. The -trial starts once you have VERIFIED YOUR EMAIL ADDRESS, and each email address -gets ONE trial. Members invited to someone else's organization do not get a trial -of their own. +Every new account starts with a 30-day free trial. No credit card is required. The trial starts once you have verified your email address. + +Each person gets **one trial**, on the first organization they own. Changing your email address does not grant a second one. Members invited to someone else's organization do not get a trial of their own. An organization you create after your first has **no trial**: it needs a payment method before you can use it, and it is billed separately, with its own $5.99 / month minimum. | Included | Amount | |----------|--------| | Storage | 1 TB (1,000 GB) | -| Egress bandwidth | 2 TB (cumulative over the trial) | +| Egress bandwidth | 2 TB (2,000 GB) | | API operations | Unlimited | | Duration | 30 days from when the trial starts | -The two caps are enforcement thresholds, not soft allowances, and behave differently: reaching the storage cap (1 TB) WRITE-LOCKS the account (reads still work), while reaching the egress cap (2 TB) DISABLES it entirely (no access), the same state as an account whose grace period has ended, with NO read-only grace period first. Trial egress is a single cumulative budget for the whole 30 days, not a monthly amount that resets. Enforcement runs on a twice-daily usage job (~07:00/19:00 UTC), so a cap can be exceeded for a few hours before access changes. Generating shareable links and viewing invoice history are the two features reserved for paid plans. +The trial gives you enough capacity to test real workloads, not just sample uploads. Almost everything works during the trial; the two exceptions are generating **shareable links** for objects and viewing **invoice history**, both of which unlock on a paid plan. + +Warning: Trial caps are enforced, and the two caps behave differently +The storage and egress figures above are hard limits, not soft allowances, and reaching them has different consequences: + +- **Storage reaching 1 TB** puts the account into a **write-locked** state — you can still read and download, but new uploads are rejected. +- **Egress reaching 2 TB** **disables the account** — the same state as an account whose grace period has ended, with no read or write access until you upgrade. There is no read-only grace period first. + +Trial egress is a **single cumulative budget** across the whole 30 days, not a monthly amount that resets. Enforcement runs on a twice-daily usage job (around 07:00 and 19:00 UTC), so a cap may be exceeded for a few hours before access changes. ## What happens when the trial ends | Phase | Days | What you can do | |-------|------|-----------------| -| Active trial | 0-30 | Full access. | -| Grace period | 31-37 | Read-only. Download your data and upgrade. | -| Expired | 38+ | Account disabled. No access to data, uploads, or API keys. | +| **Active trial** | 0-30 | Full access. Upload, download, manage data. | +| **Grace period** | 31-37 | **Read-only.** Download your data and upgrade to a paid plan. No new uploads. | +| **Expired** | 38+ | Account disabled. No access to data, uploads, or API keys. An Owner can still reactivate from **Billing**. | + +The trial ends at the end of day 30, but the read-only state is applied by a job that runs twice a day (08:00 and 20:00 UTC). Uploads over the S3 API can keep working for up to about 12 hours after the trial ends, until that job runs. + +You will receive email reminders at: +- **Day 15** -- Halfway through your trial, with an upgrade link. +- **Day 25** -- 5 days left, with an upgrade link. +- **Day 31** -- Trial ended, grace period started. +- **Day 36** -- Grace period ends in 48 hours. +- **Day 38** -- Account disabled. + +Note: +You can upgrade to a paid plan at any time during the trial or grace period, and an organization Owner can reactivate from **Billing** after the account is disabled too. Upgrading or reactivating restores full access immediately. -You can upgrade to a paid plan at any time during the trial or grace period. Disabling blocks all access to the account; Fil One does not run an automatic purge at that point, so contact support to restore access or request removal of your data. +Info: What "disabled" means +Disabling blocks all access to the account: your data is no longer reachable through the API or the dashboard, and access keys stop working. Fil One does not run an automatic purge at this point. To restore access, an organization Owner opens **Billing** and clicks **Reactivate**. To have your data removed, email [support@filone.com](mailto:support@filone.com). ## Paid plan pricing -| Component | Price | -|-----------|-------| -| Storage | $5.99 / TB / month | -| Egress bandwidth | No charge | -| API operations | Included | +| Component | Price | Notes | +|-----------|-------|-------| +| Storage | $5.99 / TB / month | Billed on average daily usage, minimum $5.99 / month. | +| Egress bandwidth | No charge | No egress fees. | +| API operations | Included | No per-request charges. | + +Pricing is usage-based, measured as the average storage consumed across the billing period, with a **$5.99 / month minimum**. If your usage works out to less than $5.99 in a billing period, you are billed the $5.99 minimum. Organizations that subscribed before the move to $5.99 keep their earlier terms; see [Pricing](https://docs.filone.com/billing/pricing). **Pay as you go** has no contract or term commitment. For volume pricing on 1, 3, or 5-year terms, the **Business plan** is arranged with the sales team. See [Billing](https://docs.filone.com/app/billing#choosing-a-plan). + +## Payment + +Payments are processed through Stripe. An organization Owner adds a credit card from Billing in the dashboard, opened from **Billing** under **Organization** in the left sidebar. See [Billing](https://docs.filone.com/app/billing). -Billed on average daily usage, with a $5.99 / month minimum. If you store less than 1 TB, you are billed the $5.99 minimum. Organizations that subscribed before the move to $5.99 keep their earlier terms (see Pricing). **Pay as you go** has no contract or term commitment; for volume pricing on 1, 3, or 5-year terms, the **Business plan** is arranged with the sales team. +- Invoices are generated monthly. +- Usage details are visible on the Billing page to Owners and Admins. +- Each invoice is charged automatically to the card on file. -Payments are processed through Stripe. An organization Owner adds a credit card from Billing in the dashboard, opened from **Billing** in the organization menu at the top of the left sidebar. Usage details are visible on the Billing page to Owners and Admins. +## Payment failures -If a payment fails, the account enters **past due** and Stripe automatically retries the charge. The DASHBOARD BECOMES READ-ONLY from the moment the payment fails, and the Billing page shows "Your last payment failed" with an "Update payment" button. If all retries are exhausted and Stripe cancels the subscription, the account moves to the paid grace period. DO NOT RELY ON AN EMAIL to learn a payment failed: check the Billing page, where an Owner fixes it with "Update payment". Cancellation is done through the Stripe billing portal, and the 30-day grace period starts when Stripe actually cancels the subscription. +If a payment fails, your account enters **past due** status and Stripe automatically retries the charge. The **dashboard becomes read-only** from the moment the payment fails, and the Billing page shows **Your last payment failed** with an **Update payment** button. + +If all retries are exhausted and the subscription is canceled by Stripe, your account transitions to the paid grace period (see below). + +Warning: Check the Billing page, not your inbox +Don't rely on an email to tell you a payment has failed. If uploads stop working, open **Billing** in the dashboard: a **Your last payment failed** banner means the card needs updating, and an Owner can fix it with **Update payment**. See [Billing](https://docs.filone.com/app/billing#your-plan). + +## Cancellation + +An organization Owner can cancel the paid plan from the **Stripe billing portal**, which opens from **Billing** in the dashboard. Admins can see usage on Billing but can't open the portal. When cancellation takes effect depends on the option you choose there: if you cancel at the end of the current billing period, your plan stays **active and billable until that period ends**. The **30-day grace period** begins only once Stripe actually cancels the subscription — not the moment you click cancel: + +| Phase | Duration | What you can do | +|-------|----------|-----------------| +| **Grace period** | 30 days | **Read-only.** Download your data or reactivate your plan. No new uploads. | +| **Expired** | After grace period | Account disabled. No access to data, uploads, or API keys. | + +Reactivating restores full access immediately, during the grace period or after the account is disabled: an organization Owner opens **Billing** and clicks **Reactivate**. Reactivating starts a new subscription, so your billing date moves to the day you reactivate. To have your data removed instead, email [support@filone.com](mailto:support@filone.com). + + +--- + +# Pricing + +Source: https://docs.filone.com/billing/pricing + +Fil One is priced at **$5.99 / TB / month**, with a **$5.99 / month minimum**. If you store less than 1 TB, you are billed the $5.99 minimum. + +No egress fees, no per-request charges, no hidden costs. + +This is the self-service **Pay as you go** plan. For volume pricing on 1, 3, or 5-year terms, the **Business plan** is arranged with the sales team. See [Billing](https://docs.filone.com/app/billing#choosing-a-plan). + +## How billing is calculated + +Your bill is based on the average amount of data you store over the billing period: + +- Stored bytes are measured as daily readings and averaged across the billing period. A metering job reports the running average **twice a day** (around 07:00 and 19:00 UTC). +- Storage is charged at a single flat rate of **$5.99 per TB per month**, applied to your average usage, with a **$5.99 / month minimum**. Any period that works out to less than $5.99 is billed at the $5.99 minimum. There is no separate "first TB" tier — it is one linear rate plus a floor. + +Storage is measured precisely and in **decimal** units (1 TB = 1,000 GB), so you are billed for what you actually store rather than being rounded up to the next whole TB. + +### Examples + +Illustrative figures for a steady amount stored for the full month, at $5.99 per TB with the $5.99 monthly minimum applied: + +| Average stored | Monthly bill | +|----------------|--------------| +| 500 GB | $5.99 (minimum applies) | +| 1 TB (1,000 GB) | ~$5.99 | +| 1.5 TB (1,500 GB) | ~$8.99 | +| 2 TB (2,000 GB) | ~$11.98 | + +Note: +These figures are illustrative. Your invoice is the source of truth for exact amounts — open the **Billing** page in the dashboard to see your current usage and charges. + +If the amount you store changes during the month, it is averaged first. For example, storing 2 TB for the first 10 days and 0.5 TB for the remaining 20 days averages to 1 TB, billed at $5.99 for that month. + +Note: If your account predates the current price +These are the prices for new customers. Organizations that subscribed before the move to $5.99 keep their earlier terms: $4.99 / TB / month with a $4.99 / month minimum, or, for accounts created before any monthly minimum was introduced, per-unit pricing with no minimum. The **Billing** page shows your own rate. --- @@ -1500,51 +1708,38 @@ If a payment fails, the account enters **past due** and Stripe automatically ret Source: https://docs.filone.com/billing/usage -The Billing page in the dashboard shows current usage for the active billing -period. It is visible to organization Owners and Admins. +The **Billing** page in the dashboard shows your current usage for the active billing period. It is visible to organization Owners and Admins. See [Billing](https://docs.filone.com/app/billing). ## What is measured | Metric | How it's measured | |--------|------------------| -| Storage | Average daily storage across the billing period, in GB or TB | -| Egress bandwidth | Total data downloaded from Fil One in the billing period | +| **Storage** | Average daily storage across the billing period, in GB or TB | +| **Egress bandwidth** | Total data downloaded from Fil One in the billing period | -Storage is measured as an average rather than a peak — storing 2 TB for half the -month and 1 TB for the other half bills 1.5 TB. Fil One counts storage in -decimal units: 1 TB is 1,000 GB, and 1 GB is 1,000,000,000 bytes. +Storage is measured as an average rather than a peak — if you store 2 TB for half the month and 1 TB for the other half, you are billed for 1.5 TB. Fil One counts storage in **decimal** units: 1 TB is 1,000 GB, and 1 GB is 1,000,000,000 bytes. -On a paid plan, egress is NOT charged — there are no egress fees. During the -trial, egress is capped. +**On a paid plan, egress is not charged** — there are no egress fees. During the trial, egress is capped (see below). + +You may see three egress figures. **Billing** shows egress for the current billing period. The **Dashboard** shows a rolling 30-day total. The trial cap counts egress cumulatively from the day the trial started. ## Trial limits During the free trial, usage is capped at: +- **Storage — 1 TB (1,000 GB):** reaching this limit **write-locks** the account. You can still read and download; new uploads are rejected. If you delete data and your storage drops back under 1 TB, the write lock lifts on the next usage run. +- **Egress — 2 TB (2,000 GB), cumulative over the whole trial:** reaching this limit **disables** the account entirely — no read or write access — the same state as an account whose grace period has ended, with no read-only grace period first. This is a single budget for the full 30 days, not a monthly amount that resets. -- Storage — 1 TB (1,000 GB): reaching this limit WRITE-LOCKS the account. Reads - and downloads still work; new uploads are rejected. If you delete data and - storage drops back under 1 TB, the write lock lifts on the next usage run. -- Egress — 2 TB (2,000 GB), cumulative over the whole trial: reaching this limit - DISABLES the account entirely — no read or write access — the same state as an - account whose grace period has ended, with no read-only grace period first. This is a single budget for the full 30 days, not a monthly - amount that resets. - -These caps are enforced by a usage job that runs twice a day (around 07:00 and -19:00 UTC), so a cap may be exceeded for a few hours before the account state -changes — there is no real-time block at the exact moment it is crossed. -Upgrading to a paid plan removes both caps immediately. +These caps are enforced by a usage job that runs **twice a day** (around 07:00 and 19:00 UTC), so you may exceed a cap for a few hours before the account state changes — there is no real-time block at the exact moment you cross it. Upgrading to a paid plan removes both caps immediately. ## Versioning and storage costs -If versioning is enabled on a bucket, every version of an object counts as -stored storage. Overwriting a 1 GB file 10 times results in 10 GB of stored -versions. +If versioning is enabled on a bucket, every version of an object counts as stored storage. Overwriting a 1 GB file 10 times results in 10 GB of stored versions. Consider deleting old versions you no longer need to reduce storage costs. See [Versioning](https://docs.filone.com/storage/versioning). ## Billing period -Paid accounts are billed monthly. The billing period resets on the same day each -month (the date of the first upgrade from trial). Usage resets at the start of -each new billing period. +Paid accounts are billed monthly. The billing period resets on the same day each month (the date you upgraded from the trial, or the date you last reactivated). Usage resets at the start of each new billing period. + +See [Trial & Billing](https://docs.filone.com/billing/trial) for pricing details. --- @@ -1553,73 +1748,58 @@ each new billing period. Source: https://docs.filone.com/app/dashboard -The console home page, reached from "Dashboard" at the top of the left sidebar. -A "New bucket" button sits in the header, and during the trial a banner shows the -days left with an "Upgrade" button. Sign-in, email verification, MFA and passkeys -are covered on Account Security. - -## Quick setup - -Until all three are done, a "QUICK SETUP" card tracks progress as "n of 3": -Create a bucket, Upload an object, Generate API key. It disappears when complete. - -## Plan, storage and egress cards - -The PLAN card is only shown to roles that can view billing (Owner and Admin); -other roles see just the storage and egress cards. - -- PLAN: plan name plus status badge (Active / Past Due / Grace Period / - Canceled / No plan). On trial the badge counts down "n days left" and hovering - shows the exact expiry. Footer link goes to Billing. -- STORAGE: usage; on trial adds "/ 1 TB" and a progress bar, on a paid plan - with a per-TB rate shows an "Est. monthly cost" row instead. -- EGRESS: usage; on trial adds "/ 2 TB" and a progress bar, on paid reads - "No egress fees · unlimited". -- A strip below shows BUCKETS / OBJECTS / API KEYS totals, with "View all" links - for buckets and API keys. - -How to read the numbers: -- SIZES ARE DECIMAL. 1 GB = 1,000,000,000 bytes, 1 TB = 1,000 GB. -- STORAGE IS A PERIODIC POINT-IN-TIME READING, not live, so a very recent upload - or delete may not be reflected yet. -- EGRESS IS A ROLLING 30-DAY TOTAL, not a calendar month, so it does not reset on - the 1st. -- "Est. monthly cost" applies your plan's per-TB price to the latest storage - reading, with the account's monthly minimum as the floor. It is not shown when - the plan has no per-TB rate. THE INVOICE IS CALCULATED FROM AVERAGE - STORAGE over the month, so the two figures differ. The estimate excludes egress - (free on paid plans). +The dashboard at [app.filone.com](https://app.filone.com) is the home page of the console, reached from **Dashboard** at the top of the left sidebar. It summarises your plan, usage, and recent activity. A **New bucket** button sits in the header. During the trial, a **Free trial** banner shows the days left and an **Upgrade** button. You can dismiss it with its **×** button. + +For sign-in methods, email verification, two-factor authentication, and passkeys, see [Account Security](https://docs.filone.com/security/account-security). + +## Get started + +A new organization opens on a **Get started** page instead of the dashboard, because its dashboard would be all zeros. The page offers **Create bucket** and **Create API key**, which change to **Create another bucket** and **Create another key** once you have one. Below them, **Explore more** links to inviting your team, these docs, and the Fil One team. The page stays at `/get-started` if you want to come back to it. + +## Plan, storage, and egress + +Three cards sit below the header. The **PLAN** card is only shown to roles that can view billing (Owner and Admin), so other roles see just the storage and egress cards. See [Roles and permissions](https://docs.filone.com/app/organization#roles-and-permissions). + +- **PLAN** shows your plan name and a status badge (**Active**, **Past Due**, **Grace Period**, **Canceled**, or **No plan**). During the trial the badge counts down as *n* **days left**, and hovering it shows the exact expiry time. The footer link goes to Billing. +- **STORAGE** shows how much you are storing. On the trial it adds a **/ 1 TB** suffix and a progress bar. On a paid plan with a per-TB rate it instead shows an **Est. monthly cost** row. +- **EGRESS** shows your egress. On the trial it adds a **/ 2 TB** suffix and a progress bar. On a paid plan it reads **No egress fees · unlimited**. + +Below those, a strip shows your **BUCKETS**, **OBJECTS**, and **API KEYS** totals, with **View all** links for buckets and API keys. + +Info: How to read these numbers +**Sizes are decimal.** 1 GB means 1,000,000,000 bytes and 1 TB means 1,000 GB, matching how your usage is billed. See [Usage](https://docs.filone.com/billing/usage). + +**Storage is the most recent reading**, sampled periodically rather than live, so a change you just made may take a little while to appear. + +**Egress is a rolling 30-day total** rather than a calendar-month figure, so it moves with the trailing month instead of resetting on the 1st. + +**Est. monthly cost is a guide.** It applies your plan's per-TB price to your latest storage reading, with your monthly minimum as the floor. It is not shown when your plan has no per-TB rate. Your invoice is calculated from your average storage across the month, so expect the two to differ. See [Pricing](https://docs.filone.com/billing/pricing). ## Usage Trends -Charts a 7-day (default) or 30-day window. STORAGE is an area chart, and the -figure above it is the most recent reading. EGRESS is a bar chart, and the figure -above it is the total egress across the window. Each point is a daily reading, -and days without a reading are plotted as zero, so a data gap appears as a dip to -zero. +**Usage Trends** charts your history over a **7 days** or **30 days** window, defaulting to 7. **Storage** is an area chart, and the figure above it is the most recent reading. **Egress** is a bar chart, and the figure above it is the total egress across the window. + +Each point is a daily reading. Days without a reading are plotted as zero, so a gap in the data appears as a dip to zero. ## Recent Activity -The five most recent events with relative timestamps ("5m ago", "2d ago"). -The feed currently covers bucket and key creation: each row shows the resource -name with a "bucket" or "key" badge and the label "Created". OBJECT-LEVEL EVENTS ARE NOT INCLUDED YET, so -confirm an upload by opening the bucket rather than by reading this feed. Empty -state: "No activity yet" plus a "Create bucket" button. +**Recent Activity** lists your five most recent events, each with a relative timestamp such as `5m ago` or `2d ago`. -## Account state banners (app-wide, not just the dashboard) +The feed currently covers bucket and key creation. Each row shows the resource name with a **bucket** or **key** badge and the label **Created**. Object-level events are not included yet, so open a bucket to confirm an upload rather than looking for it here. With no activity yet the card reads **No activity yet** and offers a **Create bucket** button. -- Trial storage cap reached: "Storage limit exceeded. Uploads are disabled. - Delete files or upgrade to resume." -- Trial expired, in grace: says the trial expired with days left to upgrade or - download data. -- Account disabled: "Account disabled. Visit billing to restore access." +## Account state banners -Roles that cannot view billing see a shorter banner that leaves out the cause: -when writes are paused it says uploads are disabled for this organization, and -when the account is disabled it says so. Both ask you to contact an organization -owner. +When your account is restricted, a banner appears above the page on every screen, not just the dashboard: -Reads keep working while writes are paused, so data stays available to download. +| Situation | What the banner says | +|-----------|----------------------| +| Trial storage cap reached | **Storage limit exceeded. Uploads are disabled. Delete files or upgrade to resume.** | +| Trial expired, in grace period | That the trial has expired, with the days left to upgrade or download your data | +| Account disabled | **Account disabled. Visit billing to restore access.** | + +Roles that cannot view billing see a shorter banner that leaves out the cause: when writes are paused it says uploads are disabled for this organization, and when the account is disabled it says so. Both ask you to contact an organization owner. + +Reads keep working while writes are paused, so your data stays available to download throughout. See [Trial & Billing](https://docs.filone.com/billing/trial) for the full lifecycle and [Usage](https://docs.filone.com/billing/usage) for how the caps are applied. --- @@ -1628,160 +1808,129 @@ Reads keep working while writes are paused, so data stays available to download. Source: https://docs.filone.com/app/buckets -Console-specific. Concepts, S3 equivalents and code samples live on Buckets, -Objects, Versioning and Object Lock. +**Buckets** in the left sidebar is where you create buckets and work with their contents without writing code. -## Bucket list +This page covers the console specifically. For the concepts, the S3 API equivalents, and code samples, see [Buckets](https://docs.filone.com/storage/buckets), [Objects](https://docs.filone.com/storage/objects), [Versioning](https://docs.filone.com/storage/versioning), and [Object Lock](https://docs.filone.com/storage/object-lock). -Columns: Name, Region (label plus region id), Created. Under each name a second -line gives the bucket's storage used and object count, and an icon marks the -bucket as private. All buckets are listed together, SORTED BY NAME. With 5 OR -MORE BUCKETS a "Search buckets" box appears, the column headers become sortable, -and a region filter appears when buckets span more than one region. Empty state: -"No buckets yet" plus "Create bucket". If one region cannot be reached, an amber -notice names it and buckets in the other regions are still listed. +## The bucket list -Each row has an actions menu: Browse objects, Copy bucket name, Copy S3 endpoint, -Delete bucket. +The table shows **Name**, **Region** (both the label and the region ID, such as Europe (France) and `eu-west-1`), and **Created**. Under each name a second line gives the bucket's storage used and object count, and an icon marks the bucket as private. -## Deleting a bucket +All of your buckets are listed together, sorted by name. Once you have 5 or more buckets, a **Search buckets** box appears above the table, the column headers become sortable, and a region filter appears when your buckets span more than one region. With no buckets yet the page reads **No buckets yet** and offers **Create bucket**. + +If one region cannot be reached, an amber notice names it and the buckets in the other regions are still listed. + +Each row has an actions menu with **Browse objects**, **Copy bucket name**, **Copy S3 endpoint**, and **Delete bucket**. + +### Deleting a bucket + +Warning: Deleting a bucket can't be undone +A deleted bucket can't be restored, and applications that use it start failing straight away. + +Choose **Delete bucket** from the row's actions menu and confirm. Only empty buckets can be deleted: if the bucket still holds objects or object versions, the console says it is not empty and links to how to empty it. Use [Empty bucket](#emptying-a-bucket) first, then delete. -"Delete bucket" from the row's actions menu, then confirm. ONLY EMPTY BUCKETS can -be deleted: if the bucket still holds objects or object versions, the console -says it is not empty and links to how to empty it. Use "Empty bucket" first, then -delete. Deletion is permanent. "Delete bucket" is shown ONLY TO OWNERS AND -ADMINS. It works in EVERY REGION, INCLUDING eu-west-1, where DeleteBucket is not -available over the S3 API (over the API it works in us-east-1 only). +**Delete bucket** is only shown to Owners and Admins. It works in every region, including `eu-west-1`, where `DeleteBucket` is not available over the S3 API. See [Buckets](https://docs.filone.com/storage/buckets#deleting-a-bucket). ## Creating a bucket -1. Bucket name: 3-63 chars, lowercase letters/numbers/hyphens, must start and end - alphanumeric, NO DOTS (unlike AWS S3), globally unique. -2. Region: eu-west-1 Europe (France) default, or us-east-1 US East (Michigan). -3. Object settings, three switches nested in order, ALL OFF BY DEFAULT: - Versioning, then Object Lock (available once Versioning is on), then Retention - (available once Object Lock is on). Turning a parent off resets what nests - inside it. Retention reveals a "Default Retention Policy": Governance - (default) or Compliance, plus a "Lock period" in Days or Years, DEFAULT 15 - DAYS, maximum 100 years. +Click **Create bucket** (or **New bucket** on the Dashboard) and fill in: -An optional "Create new key" section creates an access key alongside the bucket, -pre-scoped to that bucket and region; the submit button becomes "Create bucket -and API key" and the secret is shown once in a dialog. The console then opens the -new bucket's page. +1. **Bucket name.** 3 to 63 characters, lowercase letters, numbers, and hyphens only, starting and ending with a letter or number. No dots, unlike AWS S3. The form says it "must be unique in this region". +2. **Region.** Europe (France) `eu-west-1`, the default, or US East (Michigan) `us-east-1`. This sets the endpoint you connect to. +3. **Advanced settings**, collapsed by default because most buckets don't need them. Expand it to set three switches that build on one another, all off by default: + - **Versioning** keeps multiple versions of an object. + - **Object Lock** can't be turned on until Versioning is, and shows a **Needs Versioning** badge until then. + - **Retention** can't be turned on until Object Lock is, and shows a **Needs Object Lock** badge until then. Turning it on reveals a **Default Retention Policy** with **Governance** or **Compliance** mode (Governance by default) and a **Lock period** in **Days** or **Years**, defaulting to 15 days. The maximum is 100 years. -An "Included by default" panel states: all data encrypted at rest, and every -bucket private (access requires an API key). + Turning a switch back off resets the ones that depend on it. While the section is collapsed, the line beside it lists what is on. -PERMANENT AT CREATION: name, region, versioning, Object Lock and default -retention, in the console and over the API alike (no update-bucket operation). -Create a new bucket for a different configuration. +Click **Create bucket**. The console opens the new bucket, and its empty state offers **Create API key** (or **View API keys**, if you already have keys that reach it) so you can connect an application. + +A panel headed **Included by default** confirms two things you do not configure: all data is encrypted at rest, and every bucket is private, so access requires an API key. + +Warning: These choices are permanent +Name, region, versioning, Object Lock, and the default retention policy are all fixed when the bucket is created, in the console and over the API alike. Decide on them up front, and create a new bucket if you later need a different configuration. ## Inside a bucket -Header shows region, storage used, creation time. THREE property cards: -Versioning and Object Lock (each "Enabled" or "Disabled"), and Retention (the -default retention policy, e.g. "Compliance · 15 days", or "None"). Encryption is -on for every bucket, so it has NO CARD of its own. Once the bucket holds objects, -"Empty bucket" and "Upload object" buttons appear in the header; while it is -empty, the upload button sits in the empty state instead. -Tabs: "Objects (N)" and "API Keys (N)". The API Keys tab includes an "Access -endpoints" block with copyable S3 Endpoint, S3 Path and Region, and is hidden for -the Read-only role. - -Object table columns: Name, Size, Last Modified, plus Version and Status when -versioning is on. Keys containing "/" group into clickable folder rows with a -breadcrumb. On versioned buckets a key with >1 version gets an expander and an -"n versions" pill; badges are "Latest" and "Delete marker". Per-row icon buttons -download or delete a single object, and a checkbox on each row (and on the -header) lets you SELECT SEVERAL AT ONCE. - -LARGE BUCKETS: the browser shows the FIRST PAGE of results (~1,000 entries). When -there are more, an amber "Showing the first n" notice appears, and selecting and -deleting apply only to the objects listed. The "Objects (N)" tab count then comes -from bucket analytics, a DAILY READING THAT CAN LAG recent changes, so expect it -to be higher than the rows in view. Page through a full listing with the CLI or -an SDK, or use "Empty bucket" to remove everything. +Opening a bucket shows its region and storage used, then three property cards: **Versioning** and **Object Lock** (each **Enabled** or **Disabled**), and **Retention**, which shows the default retention policy, such as **Compliance · 15 days**, or **None**. Encryption is on for every bucket, so it has no card of its own. + +Once the bucket holds objects, **Empty bucket** and **Upload object** buttons appear in the header. While it is empty, the upload button sits in the empty state instead. + +Two tabs follow: + +- **Objects (N)** is the object browser. +- **API Keys (N)** lists the keys that can reach this bucket, plus an **Access endpoints** block with the copyable **S3 Endpoint**, **S3 Path**, and **Region** you need to configure a client. This tab is hidden for the Read-only role. + +### Browsing objects + +The object table shows **Name**, **Size**, and **Last Modified**, plus **Version** and **Status** columns when versioning is enabled. Keys containing `/` are grouped into folder rows you can click into, with a breadcrumb to walk back out. + +On a versioned bucket, a key with more than one version gets an expander and an *n* **versions** pill. Expanding shows the older versions, badged **Latest** for the current one and **Delete marker** where a delete marker sits on top. + +Per-row icon buttons download, share, or delete a single object. A checkbox on each row, and on the header, lets you select several at once. See [Deleting objects](#deleting-objects). + +Note: Large buckets +The browser shows the first page of results, around 1,000 entries. When there are more, an amber **Showing the first** *n* notice appears, and selecting and deleting apply only to the objects listed. The count on the **Objects (N)** tab then comes from your bucket analytics, a daily reading that can lag recent changes, so expect it to be higher than the number of rows in view. Use the AWS CLI or an SDK to page through a full listing, or [Empty bucket](#emptying-a-bucket) to remove everything. See [Objects](https://docs.filone.com/storage/objects). ## Uploading -"Upload object" on the bucket. Drag files OR whole folders, or use "Select files" -/ "Select folder". +Open a bucket and click **Upload object**. You can drag files or whole folders onto the drop zone, or use **Select files** and **Select folder**. + +An optional **Prefix** field puts your files under a path such as `images/`. Two details are worth knowing: -Prefix behaviour: the optional "Prefix" field appears when INDIVIDUAL FILES are -selected. Folder-selected files keep their own relative paths, which take the -place of the prefix. The prefix starts empty each time rather than carrying over -from the folder being browsed. +- The prefix field appears when you select individual files. Files picked as a folder keep their own relative paths, which take the place of the prefix. +- The prefix starts empty each time rather than carrying over from the folder you were browsing, so set it on every upload where you want one. -Folder uploads SKIP SYSTEM FILES: .DS_Store, Thumbs.db, desktop.ini, anything -whose path contains a segment starting with a dot, and __MACOSX folders. A -"Skipped n system files" message says how many were left out. A file selected on -its own is always uploaded, whatever its name. +Folder uploads skip system files that come along with a folder: `.DS_Store`, `Thumbs.db`, `desktop.ini`, anything whose path contains a segment starting with a dot, and `__MACOSX` folders. A **Skipped** *n* **system files** message tells you how many were left out. A file you select on its own is always uploaded, whatever its name. -Selecting files does not upload them; click "Upload n file(s)". A failure gives a -"Retry n failed" button that retries only those files. +Selecting files does not upload them. Click **Upload** *n* **file(s)** to start, and a per-run progress bar tracks the batch. If any file fails, a **Retry** *n* **failed** button retries just those rather than the whole set. -SINGLE-PUT, NOT MULTIPART: one request per file, capped by the S3 5 GB single-PUT -ceiling. Use the CLI or an SDK with multipart support above that. +Note: Object size +The console uploads each file in a single request, which the S3 single-PUT ceiling caps at 5 GB. For objects above that, use the AWS CLI or an SDK with multipart support. See [Multipart Uploads](https://docs.filone.com/storage/multipart-uploads). -## Object detail page +## The object detail page -Shows Name, Size, Bucket, S3 Path, ETag, and where applicable Version ID, -Retention, Description and Tags. Description and Tags are read from the object's -"description" and "tags" USER METADATA, NOT from S3 object tagging, and the -console upload flow does not set them. Compliance-mode retention adds a "Compliance -retention lock" notice with the date before which deletion is not permitted. +Clicking an object shows its **Name**, **Size**, **Bucket**, **S3 Path**, **ETag**, and, where they apply, **Version ID**, **Retention**, **Description**, and **Tags**. **Description** and **Tags** are read from the object's `description` and `tags` user metadata, not from S3 object tagging, and the console upload flow does not set them. When retention is in Compliance mode a **Compliance retention lock** notice gives the date before which the object cannot be deleted. -A "Version history" card appears when the object has more than one version, -listing Version ID / Status / Size / Last Modified and marking the one in view. -It is populated from the object listing already fetched, so arrive via the -bucket's object list rather than a direct object link to see it. +A **Version history** card appears when the object has more than one version, listing each **Version ID** with its **Status**, **Size**, and **Last Modified**, and marking the one you are viewing. Clicking another row opens that version. -NO RESTORE / PROMOTE / MAKE-CURRENT ACTION: to make an earlier version current, -download it and upload it again. +Note: Working with versions +Version history is drawn from the object list you arrived through, so open the bucket first if you have followed a direct link to an object and the card is not showing. + +To bring an earlier version back as the current one, download it and upload it again. See [Versioning](https://docs.filone.com/storage/versioning). ## Downloading and sharing -Download works on any plan INCLUDING TRIAL, from the row or the detail header. +**Download** is available on each row in the object list and in the object detail header. It works on any plan, including the trial. + +**Share object** generates a link anyone can open without an API key. Choose an expiry of **1 hour**, **24 hours** (the default), **3 days**, or **7 days**, then **Generate link**. -"Share object" generates a link needing no API key, with expiry options 1 hour / -24 hours (default) / 3 days / 7 days, then "Generate link". SHARING IS A -PAID-PLAN FEATURE: on trial the button is disabled with an upgrade tooltip. +Sharing is a paid-plan feature. During the trial the button is disabled, with a tooltip pointing to an upgrade. ## Deleting objects -Trash icon on a row, or "Delete object" on the detail page, then confirm. To -delete several at once, tick their checkboxes; a bar shows "n selected" with -"Clear" and "Delete". Ticking a folder row selects everything under it, and the -header checkbox selects everything at the current level. +Click the trash icon on a row, or **Delete object** on the detail page, and confirm. -CONSOLE DELETES ARE PERMANENT, INCLUDING ON VERSIONED BUCKETS. The console always -deletes the specific version on the row chosen and NEVER WRITES A DELETE MARKER. -On a versioned bucket, deleting the row for the current version permanently -removes that version, and the earlier versions are left as they are. To hide an -object behind a delete marker instead, delete it over the S3 API without a -version ID. +To delete several at once, tick their checkboxes. A bar shows *n* **selected** with **Clear** and **Delete**. Ticking a folder row selects everything under it, and the header checkbox selects everything at the current level. -An object under active retention or a legal hold is protected, and a delete -attempt returns that protection as an error. +Warning: Console deletes are permanent, including on versioned buckets +The console always deletes the specific version on the row you chose. It does not write a delete marker. On a versioned bucket, deleting the row for the current version permanently removes that version, and the earlier versions are left as they are. To hide an object behind a delete marker instead, delete it over the S3 API without a version ID. See [Versioning](https://docs.filone.com/storage/versioning#delete-markers). -## Emptying a bucket +An object under an active retention period or legal hold is protected, and attempting to delete it returns that protection as an error. See [Object Lock](https://docs.filone.com/storage/object-lock). -"Empty bucket" on the bucket page removes EVERY object in the bucket, including -every earlier version and delete marker. Type the bucket name to confirm, then -"Delete everything". The deletion runs ON THE SERVER, so it is not limited to the -objects listed on screen, and it keeps running if the dialog is closed. When it -finishes the dialog reports "Bucket empty", "Some objects remain" (with how many -could not be deleted, e.g. under active retention), or "Deletion stopped" if the -job could not complete. +### Emptying a bucket -Deleting objects (bulk or single) and emptying a bucket need a role that can -delete objects. Uploading and creating buckets need a role that can write objects -and create buckets. Controls you cannot use are hidden, and opening the upload or -create page directly explains that the action is not part of your role. +Danger: Empty bucket permanently deletes everything in the bucket +It removes every object, every earlier version, and every delete marker that isn't protected by retention or a legal hold. It can't be undone, and versioning doesn't protect you: nothing is kept to restore from. -While an account is past due or in a -grace period, access is read-only and writes resume once payment succeeds. +**Empty bucket** on the bucket page removes every object in the bucket, including every earlier version and delete marker. Type the bucket name to confirm, then click **Delete everything**. + +The deletion runs on the server, so it is not limited to the objects listed on screen, and it keeps running if you close the dialog. When it finishes, the dialog reports **Bucket empty**, **Some objects remain** (with how many could not be deleted, for example because they are under active retention), or **Deletion stopped** if the job could not complete. + +Deleting objects, in bulk or one at a time, and emptying a bucket all need a role that can delete objects. Uploading and creating buckets need a role that can write objects and create buckets. Controls you cannot use are hidden, and opening the upload or create page directly explains that the action is not part of your role. See [Roles and permissions](https://docs.filone.com/app/organization#roles-and-permissions). + +While an account is past due or in a grace period, access is read-only and uploads and deletions resume once the payment succeeds. See [Trial & Billing](https://docs.filone.com/billing/trial). --- @@ -1790,106 +1939,120 @@ grace period, access is read-only and writes resume once payment succeeds. Source: https://docs.filone.com/app/api-keys -Console-specific. Permission meanings, signing and security guidance live on API -Keys and Authentication. +**API Keys** in the left sidebar is where you create the S3 credentials your tools and code use. + +This page covers the console specifically. For what each permission allows, how signing works, and security guidance, see [API Keys](https://docs.filone.com/security/api-keys) and [Authentication](https://docs.filone.com/security/authentication). -## Key list +## The key list -Tabs "API keys" and "Connection details". Columns: Name (with Access Key ID and a -copy button), Region (e.g. eu-west-1; hidden on narrow screens), Buckets ("All -Buckets" or per-bucket badges), Permissions (badges, with finer-grained ones -grouped as "Data protection" / "Bucket management" / "Bucket info"), Created by -(the member who created the key, plus "Rotated by … on …" once rotated; shown -when the organization has more than one member), Status, Last Used, and a "⋯" -menu with Rotate and Delete for the keys you can act on. Empty state: "No API -keys yet" plus "Create your first key". If the account is disabled, the page -shows only a notice asking you to reactivate your subscription, with no keys, -tabs, or "Create new key" button. +The page has two tabs, **API keys** and **Connection details**. The table shows: -PLACEHOLDER COLUMNS: "Last Used" reads "Never" and "Status" reads "Active" for -every key, and the expiry date set at creation is not shown in this list. Do not -infer from these columns whether a key is in use or still valid; advise keeping -an external record and using descriptive key names. +| Column | What it holds | +|--------|---------------| +| **Name** | The key name, with the Access Key ID underneath and a copy button | +| **Region** | The region the key belongs to, such as `eu-west-1` (hidden on narrow screens) | +| **Buckets** | **All Buckets**, or one badge per bucket the key is scoped to | +| **Permissions** | Badges for the object permissions (**Read**, **Write**, **List**, **Delete**), and a **+***n* badge for the rest. Open the key to see them all | +| **Created by** | The member who created the key, and **Rotated by … on …** once it has been rotated. Shown when your organization has more than one member | +| **Status** | **Active**, or **Expired** once the key's expiry date has passed | +| **⋯** | **Rotate** and **Delete**, for the keys you can act on | + +With 5 or more keys, a **Search keys** box (by name or Access Key ID) and filters for region (**All regions**) and status (**All statuses**) appear above the table. + +Click a key's row to open its details: its **Status**, when it **Expires** (or **Never**), when it was **Created** and **Rotated**, its **Region**, which **Buckets** it reaches ("All buckets in this region" for an unscoped key), and its full **Object permissions** and **Bucket management** permissions. The details panel is the place to check a key's expiry date. + +With no keys yet the page reads **No API keys yet** and offers **Create your first key**. A Member sees "You can only see the keys you create. Owners and Admins see every key in the organization." instead, because the organization may hold keys they aren't shown. + +If your account is disabled, the **API Keys** page shows only a notice asking you to reactivate your subscription, with no keys, tabs, or **Create new key** button. + +Note: Name keys for what uses them +The console doesn't show when a key was last used. Give each key a descriptive name, such as `backup-job-prod`, so you can tell from the list which application would break if you deleted it. ## Who can manage keys -Depends on the member's organization role: -- READ ONLY members cannot create keys. The API keys tab explains that keys are - managed by members who can create them; the Connection details tab is still - available. -- MEMBERS see, rotate, and delete only the keys they created themselves. -- ADMINS and OWNERS see and manage every key in the organization. +What you can do here depends on your [role](https://docs.filone.com/app/organization#roles-and-permissions): -ROLE CEILING: a key can only carry permissions the creator's role holds, and the -form hides the ones it doesn't. "Set retention" and "Set legal hold" are -OWNER-ONLY, so they appear only for Owners. If a member's role is narrowed, any -key they created that the new role couldn't create is revoked, and removing a -member revokes the keys they created. +- **Read only** members cannot create keys. The **API keys** tab explains that keys are managed by members who can create them, and the **Connection details** tab is still available. +- **Members** see, rotate, and delete only the keys they created themselves. +- **Admins** and **Owners** see and manage every key in the organization. + +A key can only carry permissions your role holds, and the form hides the ones it doesn't. **Set retention** and **Set legal hold** are Owner-only, so they appear only for Owners. If a member's role is narrowed, any key they created that the new role couldn't create is revoked, and removing a member revokes the keys they created. The member is emailed a list of the revoked keys. See [Organization](https://docs.filone.com/app/organization#removing-a-member). ## Creating a key -Dedicated page via "Create new key". - -- Key name: up to 64 chars, letters/numbers/spaces/underscores/hyphens/periods, - unique within a region. Names starting with "filone-console" (any - capitalization) are RESERVED. -- Region: REQUIRED, pre-set to eu-west-1. A key is scoped to its region, and each region has its own - endpoint, so endpoint + region + key must agree. Storing in both regions needs - one key per region. -- Object permissions: Read (download/retrieve), Write (upload/overwrite), List - (browse/list), Delete (permanently remove). READ, WRITE AND LIST ARE - PRE-SELECTED; DELETE IS NOT. -- Finer-grained permissions nest under a checked parent and are granted - INDIVIDUALLY: under Read = Read object versions, Read retention settings, Read - legal hold status; under Write = Set retention, Set legal hold; under List = - List object versions; under Delete = Delete object versions. A key with Write - therefore also needs "Set retention" ticked before it can apply a retention - policy. Unchecking a parent clears what nested under it. -- Bucket management: "List all buckets" is always on. "Read bucket versioning" - and "Read object lock configuration" are available in every region and are - PRE-SELECTED. "Create bucket" / "Delete bucket" are available only in regions - supporting bucket management over the S3 API; in eu-west-1 they are disabled - with tooltip "Not supported in Europe (France)", where buckets are created in - the console instead. -- Bucket scope: "All buckets" (default, meaning all buckets in the key's region) - or "Specific buckets", listed filtered to the selected region. -- Expiration: "Never expires" (default), "30 days", or "Custom" date. Enforced by - the storage layer. -- Click "Create API key" to create it. - -## The secret - -A "Save your credentials" dialog shows the Access Key ID and the Secret Access -Key (masked until revealed), with copy buttons and .csv / .env downloads. -FIL ONE NEVER STORES THE SECRET, which is why it appears only when a key is -created or rotated and cannot be retrieved later. Lose it and ROTATE the key to -get a new secret. +Click **Create new key**, which opens a dedicated page. + +**Key name.** Up to 64 characters, using letters, numbers, spaces, underscores, hyphens, and periods. Names must be unique within a region, and names starting with `filone-console` (in any capitalization) are reserved. + +**Region.** Required, and pre-set to `eu-west-1`. A key is scoped to the region you pick, and each region has its own endpoint, so the endpoint, the region, and the key all need to agree. If you store data in both regions, create a key for each. + +**What can this key do?** Object permissions are: + +| Permission | Allows | +|------------|--------| +| **Read** | Download and retrieve objects | +| **Write** | Upload and overwrite objects | +| **List** | Browse and list objects | +| **Delete** | Permanently remove objects | + +**Read**, **Write**, and **List** are pre-selected. **Delete** is not. For a read-only key, untick **Write**: a key with **Write** can overwrite any object it reaches. + +Checking one of those reveals finer-grained permissions nested underneath it. These are granted individually, so tick the ones you need: + +- Under **Read**: **Read object versions**, **Read retention settings**, **Read legal hold status** +- Under **Write**: **Set retention**, **Set legal hold** +- Under **List**: **List object versions** +- Under **Delete**: **Delete object versions** + +A key with **Write** therefore needs **Set retention** ticked as well before it can apply a retention policy. Unchecking a parent clears whatever was nested under it. + +**Bucket management** is a separate section: + +- **List all buckets** is always on. +- **Read bucket versioning** and **Read object lock configuration** are available in every region, and both are pre-selected. +- **Create bucket** and **Delete bucket** are available in the regions that support bucket management over the S3 API. In `eu-west-1`, the default region, they are disabled with the tooltip **Not supported in Europe (France)**, and you create buckets in the console instead. + +**Which buckets can this key access?** Defaults to **All buckets**, meaning every bucket in the key's region. Choose **Specific buckets** to pick from a list, filtered to the region you selected. + +**When should it expire?** **Never expires** (the default), **30 days**, or **Custom** with a date picker. A key with an expiry date works through the whole of that day (UTC) and stops at the start of the next one. + +Click **Create API key** to create it. + +## Saving the secret + +On success a **Save your credentials** dialog shows the **Access Key ID** and the **Secret Access Key**, with the secret masked until you reveal it. You can copy either, or download the pair as a `.csv` or `.env` file. + +A downloaded file holds the secret in plain text. Move the values into your password manager, secrets store, or your tool's credential file, then delete the download. Never commit it: if you keep a `.env` in a project, add it to `.gitignore` first. + +Warning: The secret is shown once +Fil One never stores your secret, which is why it appears only when a key is created or rotated. Copy or download it before closing the dialog. If you lose it, [rotate the key](#rotating-a-key) to get a new secret. ## Rotating a key -Row "⋯" menu, then "Rotate". The "Rotate access key" dialog explains the key -keeps its name, permissions, and buckets and gets a NEW ACCESS KEY ID AND SECRET; -region and expiry date carry over too. Confirm with "Rotate key" and the "Save -your credentials" dialog opens with the new pair, shown once as at creation. +Open the **⋯** menu on the key's row and choose **Rotate**. The **Rotate access key** dialog explains that the key keeps its name, permissions, and buckets, and gets a new Access Key ID and secret. Its region and expiry date carry over too. Confirm with **Rotate key**, and the **Save your credentials** dialog opens with the new pair, shown once as at creation. + +The old secret stops working as soon as the new one is issued, so update anything that uses the key. If the old key can't be revoked, a message says the new credentials are ready but the key they replace is still active. Delete the old key from the list yourself in that case. + +A few limits apply: + +- An expired key can't be rotated. Create a new key instead. +- **Rotate** only appears on keys your current role could still create. See [Who can manage keys](#who-can-manage-keys). -The OLD SECRET STOPS WORKING as soon as the new one is issued, so update anything -that uses the key. If the old key can't be revoked, a message says the new -credentials are ready but the key they replace is still active; delete the old -key from the list yourself in that case. An EXPIRED key can't be rotated (create -a new key instead). "Rotate" only appears on keys your current role could still -create. After a rotation, the "Created by" column shows who rotated the key and -when. +After a rotation, the **Created by** column shows who rotated the key and when. -## Revoking +## Revoking a key -Row "⋯" menu, then "Delete": the key is permanently revoked and applications -using it lose access immediately. Deletion IS the revocation. To move an -application onto a key with different permissions or buckets, create the new key -first, switch the application over, then delete the old one. Revocation is confirmed with -the storage operator BEFORE the key leaves the list, so a listed key is a live -key and the list stays a truthful picture of access. +Warning: Deleting a key breaks anything that uses it +A deleted key stops working immediately and can't be restored. To move an application onto a key with different permissions or buckets, create the new key first, switch the application over, then delete the old one. -A bucket's "API Keys" tab lists the keys that can reach that one bucket. +Open the **⋯** menu on the key's row and choose **Delete**. The dialog warns that the key will be permanently revoked and that any application using it loses access immediately. Deleting a key is how you revoke it. + +To delete several keys at once, tick their checkboxes (or the header checkbox). A bar shows *n* **selected** with **Clear** and **Delete**. Only keys you're allowed to delete can be selected. + +A key stays in your list until its revocation is confirmed, so a key that is still listed is a key that still works. + +Note: Keys for a bucket +A bucket's **API Keys** tab shows the keys that can reach that bucket, which is a quicker way to audit access for one bucket than reading down the full list. --- @@ -1898,26 +2061,25 @@ A bucket's "API Keys" tab lists the keys that can reach that one bucket. Source: https://docs.filone.com/app/ai-agent-toolkit -Under the "AI Tools" sidebar group. +**AI Agent Toolkit** sits under **AI Tools** in the left sidebar. + +Note: Coming soon +The AI Agent Toolkit is marked **Coming Soon** in the console. The page introduces what it will offer and collects waitlist interest, so there is nothing to set up on it yet. + +## Joining the waitlist -NOT RELEASED. The page is marked "Coming Soon": it introduces what the toolkit -will offer and collects waitlist interest, so THERE IS NOTHING TO SET UP on it -yet. Stated as free during early access, with standard storage rates on the data -itself. +The form asks which tools you are looking to connect (Claude, Cursor, Continue, ChatGPT, Zapier, n8n, Make.com, or your own answer), your timeline, your team size, and any notes. The team uses it to prioritise the first wave of invitations, so naming your actual tools is more useful than picking the closest option. -Waitlist form: which tools you are connecting (Claude, Cursor, Continue, ChatGPT, -Zapier, n8n, Make.com, or your own answer), timeline, team size, notes. +The page states that the toolkit will be free during early access, with standard Fil One storage rates applying to the data itself. -## Connecting AI tools today (this part is real) +## Connecting AI tools today -The toolkit is NOT required to use Fil One from an AI application. Fil One is -S3-compatible, so anything that speaks S3 works now with an ordinary access key: -create a key scoped to the buckets the application should reach, then point the -tool at the region's endpoint with path-style addressing. Frameworks that read -and write object storage directly (LangChain, LlamaIndex, Vercel AI SDK, CrewAI) -connect this way, and a single-bucket key keeps an agent in its own workspace. +You do not need the toolkit to use Fil One from an AI application. Fil One presents an S3-compatible API, so anything that speaks S3 works now with an ordinary access key: -Treat the access-key route above as the supported way to connect AI tools today. +1. Create an access key scoped to the buckets you want the application to reach. See [API Keys](https://docs.filone.com/app/api-keys). +2. Point the tool at your region's endpoint with path-style addressing enabled. See [SDKs & Tools](https://docs.filone.com/sdk/overview). + +Frameworks that read and write object storage directly, such as LangChain, LlamaIndex, the Vercel AI SDK, and CrewAI, connect this way, and scoping the key to a single bucket keeps an agent inside its own workspace. --- @@ -1926,214 +2088,222 @@ Treat the access-key route above as the supported way to connect AI tools today. Source: https://docs.filone.com/app/organization -BETA. Organizations are in beta. Inviting teammates is switched on by Fil One for -selected organizations, so what you see depends on whether yours is one of them. -Details may change before general availability. - -Every Fil One account starts as a ONE-PERSON ORGANIZATION, with you as its -OWNER. Everything about the organization itself (name and logo, members, billing, -history) is reached from the ORGANIZATION MENU at the top of the left sidebar. +Every Fil One account starts as a one-person organization, with you as its **Owner**. You can invite teammates, give each one a role, and see what has changed in the organization. -## The organization menu +## Where to find the organization's pages -Click the organization's logo and name at the top of the sidebar. The menu lists -the organization's pages; you only see the entries your role can open. EACH IS A -SEPARATE PAGE (there are no tabs for billing or the audit log any more): +The organization's pages are in the **Organization** group of the left sidebar. You only see the entries your role can open: -| Entry | Page | What it holds | Who sees it | -|-------|------|---------------|-------------| -| Edit organization | /edit-organization | Name, logo, Owner-only Danger zone | Owner, Admin | -| Members | /members | Members and Invitations tabs | Every role, beta only | -| Billing | /billing | Plan, usage, payment method, invoices | Owner, Admin | -| Audit log | /audit | Membership, key, and organization changes | Owner, Admin, beta only | +| Entry | What it opens | Who sees it | +|-------|---------------|-------------| +| **Members** | Everyone in the organization, and pending invitations (see [Members](#members)) | Every role | +| **Billing** | Your plan, usage, payment method, and invoices (see [Billing](https://docs.filone.com/app/billing)) | Owner, Admin | +| **Audit log** | A record of membership, key, and organization changes (see [Audit log](#audit-log)) | Owner, Admin | -Below the pages the menu -lists your organizations if you belong to more than one, and, in the beta, -"Create organization". +The organization's logo and name sit at the top of the left sidebar. Click them to open the **organization menu**, which holds: -With NO ACTIVE PLAN, every page except Settings, Edit organization and Support is -replaced by "Add a payment method to continue", so Members, Billing and Audit log -are left out of the menu until a plan is in place. +- **Edit organization**, for Owners and Admins: the organization's name and logo, and how to delete it (see [Editing the organization](#editing-the-organization)) +- your organizations, if you belong to more than one (see [Switching organizations](#switching-organizations)) +- **Create organization**, for every role (see [Creating another organization](#creating-another-organization)) -## The organizations beta +Each page has its own address: `/edit-organization`, `/members`, `/billing`, and `/audit`. -Members, Audit log, Create organization and SENDING INVITATIONS are part of the -organizations beta, switched on by Fil One for selected organizations. Outside -it those entries don't appear, and opening /members or /audit directly goes to -the dashboard. Edit organization and Billing are available to every -organization. To ask about access, email support@filone.com. +While an organization has no active plan, every page except Settings, Edit organization, and Support is replaced by **Add a payment method to continue**, and the sidebar's page links are hidden until a plan is in place. See [Billing](https://docs.filone.com/app/billing). ## Editing the organization -"Edit organization" (Owners and Admins) has two sections: -- "General": the logo (saves as soon as it uploads) and "Organization name" - (needs "Save"; 2 to 100 characters, letters, numbers, spaces, hyphens, periods - only). Every member sees the change. -- "Danger zone": Owners only; deleting the organization (see below). -Members and Read only members see "Organization details are managed by your -organization's owners and admins." +**Edit organization**, for Owners and Admins, opens a page with two sections: + +- **General** holds the organization's logo and **Organization name**. A new logo saves as soon as it uploads. A new name needs **Save**, and must be 2 to 100 characters, using letters, numbers, spaces, hyphens, and periods only. Every member sees the change. +- **Danger zone**, shown to Owners only, covers deleting the organization (see [Deleting an organization](#deleting-an-organization)). + +Members and Read only members who open the page see "Organization details are managed by your organization's owners and admins." ## Creating another organization -In the beta, "Create organization" in the organization menu asks for an -"Organization name" (same rules) and an optional logo. You become the new -organization's Owner and the console switches to it straight away. A new -organization has its own members, keys, buckets, and billing. +**Create organization** in the organization menu opens a dialog asking for an **Organization name**, with the same rules as above, and an optional logo. You become the new organization's Owner, and the console switches to it straight away. A new organization has its own members, keys, buckets, and billing, separate from the organization you created it from. You can own up to **10** organizations. Organizations you were invited into don't count toward that. + +Warning: A new organization has no free trial +Each person gets one [free trial](https://docs.filone.com/billing/trial), on the first organization they own. An organization you create after that has no trial: it shows **Add a payment method to continue** until you add one, and it is billed separately, with its own monthly minimum. See [Pricing](https://docs.filone.com/billing/pricing). ## Roles and permissions -Every member holds EXACTLY ONE of four roles: +Every member holds exactly one of four roles. The role picker describes them like this: | Role | Description | |------|-------------| -| Owner | Can do everything, including billing and owning the organization. | -| Admin | Can manage members, buckets, and keys, but not billing or owners. | -| Member | Can read and write objects, and create buckets and their own keys. | -| Read only | Can read buckets and objects, but can't make changes. | +| **Owner** | Can do everything, including billing and owning the organization. | +| **Admin** | Can manage members, buckets, and keys, but not billing or owners. | +| **Member** | Can read and write objects, and create buckets and their own keys. | +| **Read only** | Can read buckets and objects, but can't make changes. | + +The full set of capabilities: | Capability | Owner | Admin | Member | Read only | -|------------|-------|-------|--------|-----------| -| See the member list | yes | yes | yes | yes | -| Invite members, change roles, remove members (Admin and below) | yes | yes | no | no | -| Make someone an Owner, change an Owner's role, remove an Owner | yes | no | no | no | -| Transfer ownership | yes | no | no | no | -| Rename the organization | yes | yes | no | no | -| View billing (plan, usage, invoices) | yes | yes | no | no | -| Manage billing (plan, payment method, Stripe portal) | yes | no | no | no | -| View and export the audit log | yes | yes | no | no | -| List buckets and read their settings | yes | yes | yes | yes | -| Create buckets | yes | yes | yes | no | -| Delete buckets | yes | yes | no | no | -| View and download objects | yes | yes | yes | yes | -| Upload objects | yes | yes | yes | no | -| Delete objects | yes | yes | yes | no | -| Create access keys | yes | yes | yes | no | -| See and revoke the keys you created | yes | yes | yes | no | -| See and revoke every key in the organization | yes | yes | no | no | -| Create keys with PutObjectRetention or PutObjectLegalHold | yes | no | no | no | - -Read only members don't see "API Keys" in the sidebar. - -ROLES APPLY IN THE CONSOLE; ACCESS KEYS CARRY THEIR OWN PERMISSIONS. The S3 API -has no users or roles. A request made with an access key is allowed or refused by -that key's own permissions and bucket scope, whoever created it. What keeps keys -in line with roles is a CAP AT CREATION: a key can only carry permissions its -creator's role holds (e.g. a Member can't create a key with DeleteBucket, and -only an Owner can create one with PutObjectRetention or PutObjectLegalHold). When -a member's role narrows, keys that go beyond the new role are revoked. +|------------|:-----:|:-----:|:------:|:---------:| +| See the member list | ✅ | ✅ | ✅ | ✅ | +| Invite members, change roles, and remove members (Admin and below) | ✅ | ✅ | — | — | +| Make someone an Owner, change an Owner's role, or remove an Owner | ✅ | — | — | — | +| Transfer ownership | ✅ | — | — | — | +| Rename the organization | ✅ | ✅ | — | — | +| View billing (plan, usage, invoices) | ✅ | ✅ | — | — | +| Manage billing (plan, payment method, Stripe portal) | ✅ | — | — | — | +| View and export the audit log | ✅ | ✅ | — | — | +| List buckets and read their settings | ✅ | ✅ | ✅ | ✅ | +| Create buckets | ✅ | ✅ | ✅ | — | +| Delete buckets | ✅ | ✅ | — | — | +| View and download objects | ✅ | ✅ | ✅ | ✅ | +| Upload objects | ✅ | ✅ | ✅ | — | +| Delete objects | ✅ | ✅ | ✅ | — | +| Create access keys | ✅ | ✅ | ✅ | — | +| See and revoke the keys you created | ✅ | ✅ | ✅ | — | +| See and revoke every key in the organization | ✅ | ✅ | — | — | +| Create keys with the `PutObjectRetention` or `PutObjectLegalHold` permission | ✅ | — | — | — | + +Read only members don't see **API Keys** in the sidebar, because they can't create or manage keys. + +Note: Roles apply in the console. Access keys carry their own permissions. +The S3 API has no users or roles. A request made with an access key is allowed or refused by that key's own permissions and [bucket scope](https://docs.filone.com/security/api-keys#bucket-scope), whoever created it. What keeps keys in line with roles is a cap at creation: a key can only carry permissions its creator's role holds. For example, a Member can't create a key with `DeleteBucket`, and only an Owner can create one with `PutObjectRetention` or `PutObjectLegalHold`. When a member's role narrows, keys that go beyond the new role are revoked (see [Changing a role](#changing-a-role)). ## Members -"Members" in the organization menu opens a page headed "Members" ("People with -access to this organization.") with up to two tabs, each with a count: Members -(every role) and Invitations (Owner, Admin). Owners and Admins also get an "Add -member" button beside the heading. - -Members tab columns: Member (name, a "You" badge on your own row, user ID underneath), Role -(a role picker if you can change this member's role, otherwise a badge), Joined -(when, and how: "Signed up", "Original account", or "Invited"; hidden on narrow -screens), and a "⋯" menu with "Transfer ownership" and "Remove" for members you -can act on. With 5 or more members, a search box and a role filter appear. - -Changing a role: Owners and Admins use the picker in the Role column, which only -offers roles you're allowed to assign. An Admin can move people between Admin, -Member, and Read only, but can't change an Owner's role or make anyone an Owner. -- Making someone an Owner asks you to confirm first (they'll be able to manage - billing, every member, and the organization itself, including removing you). -- Moving someone to a role with FEWER permissions opens a preview of their access - keys. Any key that carries more than the new role allows is listed, and the - confirm button becomes "Change role and revoke". THOSE KEYS STOP WORKING - STRAIGHT AWAY; to keep a client running, create a narrower replacement key - first. Moving someone to Read only revokes EVERY key they created. -- Moving someone to a role with more permissions takes effect immediately. -You can change your own role too; the dialog warns you if the change takes away -your ability to manage members or billing. - -Removing a member: "Remove" in the row's "⋯" menu, confirm with "Remove member". -The person loses access, and EVERY ACCESS KEY THEY CREATED IS REVOKED. Their -pending invitations are withdrawn too. Admins can remove Admins, Members, and -Read only members; only an Owner can remove an Owner. Owners and Admins can -remove themselves; Members and Read only members can't. - -AT LEAST ONE OWNER: a role change or removal that would leave the organization -with no Owner is refused ("An organization keeps at least one owner"). - -Transferring ownership: an Owner uses "Transfer ownership" in another member's -"⋯" menu. The other member becomes Owner and YOU MOVE TO ADMIN, and you can't -take ownership back yourself. Any of your keys carrying permissions an Admin -can't hold (e.g. PutObjectRetention, PutObjectLegalHold) are listed and REVOKED -as part of the transfer. Type the organization's name to confirm, then "Transfer -ownership"; this cannot be undone. Needs a RECENT SIGN-IN: if you haven't signed -in within the last five minutes, the console sends you through sign-in again -(including your two-factor check if set up) and reopens the dialog. Billing is -not affected: the subscription belongs to the organization, not the Owner. +**Members** in the sidebar opens a page headed **Members**, "People with access to this organization." It has up to two tabs, each with a count beside its label: + +| Tab | What it holds | Who sees it | +|-----|---------------|-------------| +| **Members** | Everyone in the organization and their role | Every role | +| **Invitations** | Invitations that have been sent but not yet accepted | Owner, Admin | + +Owners and Admins also get an **Add member** button beside the heading, which opens the invitation form (see [Invitations](#invitations)). + +The **Members** tab lists everyone in the organization: + +| Column | What it holds | +|--------|---------------| +| **Member** | The member's name, a **You** badge on your own row, and their user ID underneath | +| **Role** | A role picker, if you can change this member's role, or a role badge otherwise | +| **Joined** | When they joined, with how: **Signed up**, **Original account**, or **Invited** (hidden on narrow screens) | +| **⋯** | **Transfer ownership** and **Remove**, for the members you can act on | + +With 5 or more members, a search box and a role filter appear above the table. + +### Changing a role + +Owners and Admins change a role from the picker in the **Role** column. The picker only offers roles you're allowed to assign: an Admin can move people between Admin, Member, and Read only, but can't change an Owner's role or make anyone an Owner. + +- **Making someone an Owner** asks you to confirm first, because they'll be able to manage billing, every member, and the organization itself, including removing you. +- **Moving someone to a role with fewer permissions** opens a preview of their access keys first. Any key that carries more than the new role allows is listed, and the confirm button becomes **Change role and revoke**. Those keys stop working straight away, and the member is emailed a list of them. To keep a client running, create a replacement key with the narrower permissions first, then change the role. Moving someone to Read only revokes every key they created, since Read only can't hold keys. +- **Moving someone to a role with more permissions** takes effect immediately. + +You can change your own role too. The dialog warns you if the change takes away your ability to manage members or billing. + +### Removing a member + +Warning: Removing a member breaks their keys +Every access key the person created stops working the moment you confirm. If an application uses one of their keys, create a replacement key and switch the application to it first. + +Choose **Remove** from the row's **⋯** menu and confirm with **Remove member**. The person loses access to the organization, and **every access key they created is revoked**, so anything still using one stops working straight away. Invitations they sent that are still pending are withdrawn too. The person is emailed a list of the keys that were revoked. + +Admins can remove Admins, Members, and Read only members. Only an Owner can remove an Owner. Owners and Admins can remove themselves. Members and Read only members can't remove themselves, so ask an Owner or Admin. + +### At least one Owner + +An organization always keeps at least one Owner. A role change or removal that would leave it with none is refused, and the page shows **An organization keeps at least one owner**. Make someone else an Owner, or [transfer ownership](#transferring-ownership), first. + +### Transferring ownership + +An Owner can hand the Owner seat to another member with **Transfer ownership** in that member's **⋯** menu. + +1. The dialog explains that the other member becomes Owner and **you move to Admin**, and that you can't take ownership back yourself. +2. If any of your access keys carry permissions an Admin can't hold (such as `PutObjectRetention` or `PutObjectLegalHold`), the dialog lists them. They're revoked as part of the transfer. +3. Type the organization's name to confirm, then click **Transfer ownership**. This cannot be undone. + +Transferring needs a recent sign-in. If you haven't signed in within the last five minutes, the console sends you through sign-in again, including your two-factor check if you have one set up, and then reopens the dialog. + +Billing is not affected: the subscription belongs to the organization, not to the Owner. ## Invitations -Sending needs an Owner or Admin role AND an organization in the beta. Managed -from the Invitations tab of the Members page. -1. "Add member" on the Members page. 2. Enter the Email address. 3. Choose a Role (only roles you -can assign: an Admin can invite Admins, Members, and Read only; an Owner can -also invite Owners; "Member" is the default). 4. "Send invitation". - -The person joins as soon as they accept, at the chosen role. The link is -SINGLE-USE and EXPIRES IN 14 DAYS. At most 25 PENDING INVITATIONS per -organization; revoke one to send another. Re-inviting an address with a pending -invitation replaces the old one. If the email couldn't be sent, the tab says so -and offers "Send again". - -Invitations tab columns: Email (and when invited), Role, Status ("Waiting", "Not -delivered", or "Expired"), Expires (hidden on narrow screens). "Revoke" -withdraws an invitation; "Resend" appears on undelivered ones. You can only act -on invitations for roles you're allowed to assign. - -Accepting: the email links to app.filone.com/invite/accept (sign in first if -needed). Outcomes: "Welcome to " (joined, with your role and -"Continue to "); "You're already in "; "Wrong -account signed in" (sign out and sign in with the invited address); "Verify your -email address first"; "This invitation is no longer valid" (used, revoked, or -expired; ask for a new one). +Invitations are how anyone else joins your organization. Sending them needs an Owner or Admin role. They're managed from the **Invitations** tab of the [Members](#members) page. + +### Sending an invitation + +1. Click **Add member** at the top of the **Members** page. +2. Enter the person's **Email address**. +3. Choose a **Role**. Each role is listed with its description, and the list only includes roles you can assign: an Admin can invite Admins, Members, and Read only members, and an Owner can also invite Owners. **Member** is selected by default. +4. Click **Send invitation**. + +The person joins as soon as they accept, at the role you chose. The invitation link can only be used once, and expires in **14 days**. + +An organization can have at most **25** invitations pending at once. At the limit, revoke one to send another. Inviting an address that already has a pending invitation replaces the old one rather than taking a second slot. + +If the invitation was created but the email couldn't be sent, the tab says so and offers **Send again**. + +### The Invitations tab + +| Column | What it holds | +|--------|---------------| +| **Email** | The address invited, and when | +| **Role** | The role they'll join at | +| **Status** | **Waiting**, **Not delivered** (the email couldn't be sent), or **Expired** | +| **Expires** | When the link stops working (hidden on narrow screens) | + +**Revoke** withdraws an invitation, and the link stops working. **Resend** appears on invitations whose email was not delivered. You can only act on invitations for roles you're allowed to assign. + +### Accepting an invitation + +The invitation email links to `app.filone.com/invite/accept`. If you're not signed in, you're asked to sign in first and then brought back. The page then shows one of these: + +| Outcome | What it means | +|---------|---------------| +| **Welcome to** *organization* | You've joined. The page shows your role and what it lets you do, with **Continue to** *organization*. | +| **You're already in** *organization* | You were already a member. | +| **Wrong account signed in** | The invitation was sent to a different address than the one you're signed in with. Log out, sign in with the right address, and open the link again. | +| **Verify your email address first** | Your email isn't verified yet. Verify it, and you're brought back to accept. | +| **This invitation is no longer valid** | The link has already been used, was revoked, or has expired. Ask an administrator for a new invitation. | ## Switching organizations -With more than one membership, the ORGANIZATION MENU lists your organizations -under "Organization", sorted by name, with a check mark on the current one; -choosing another switches the console to it and opens its dashboard. With one -membership the list doesn't appear. The choice is kept PER BROWSER TAB, so two -tabs can be in different organizations. The sidebar names the current -organization; check it before removing people or transferring ownership. +If you belong to more than one organization, the organization menu lists them under **Organization**, sorted by name, with a check mark on the one you're in. Choosing another switches the console to that organization and opens its dashboard. With only one membership, the list doesn't appear. + +The choice is kept per browser tab, so two tabs can be in different organizations at the same time. The sidebar names the organization you're in, so check it before removing people or transferring ownership. + +### Leaving an organization -Leaving: the "Organizations" section of Settings lists every organization you -belong to (role, when you joined); each row's menu offers "Switch to this -organization" and "Leave organization". Leaving removes your access to that -organization and everything in it; you can only rejoin with a new invitation. -THE LAST OWNER CAN'T LEAVE: make someone else an Owner first. +The **Organizations** section of [Settings](https://docs.filone.com/app/settings) lists every organization you belong to, with your role and when you joined. Each row's menu offers **Switch to this organization** and **Leave organization**. Leaving removes your access to that organization and everything in it, and you can only rejoin with a new invitation. The last Owner of an organization can't leave it: make someone else an Owner first (see [At least one Owner](#at-least-one-owner)). ## Audit log -Its own page (/audit), from "Audit log" in the organization menu. Owners and -Admins. Columns: Event, Member, Subject (hidden on narrow screens), -When; expand a row for details. Filter by date range (From, To), event type -("All events"), and member ("Anyone"). +**Audit log** in the sidebar opens a page, for Owners and Admins, that records changes to the organization: -Events recorded: organization created / renamed; member invited, invitation -revoked, invitation accepted; role changed, member removed, ownership -transferred; key created, key deleted, key rotated; audit log exported. +| Column | What it holds | +|--------|---------------| +| **Event** | What happened | +| **Member** | Who did it | +| **Subject** | What it was done to (hidden on narrow screens) | +| **When** | When it happened | -"Download CSV" exports events matching the current filters, UP TO 20,000 ROWS; a -larger export is REFUSED rather than cut short, so narrow the filters. Events are -KEPT FOR 90 DAYS; a range reaching further back says the older events have been -removed. +Expand a row to see its details. Filter by date range (**From**, **To**), by event type (**All events** by default), and by member (**Anyone** by default). + +Events recorded: + +- Organization created, organization renamed, and organization logo updated +- Member invited, invitation revoked, and invitation accepted +- Role changed, member removed, and ownership transferred +- Key created, key deleted, and key rotated +- Audit log exported + +**Download CSV** exports the events that match your current filters. An export can hold up to 20,000 rows. A larger one is refused rather than cut short, so narrow the date range or filter by event type or member. + +Events are kept for **90 days**. If you ask for a range that reaches further back, the page tells you the older events have been removed. ## Billing -"Billing" in the organization menu opens the billing page (/billing), for -Owners and Admins (see App: Billing). +**Billing** in the sidebar opens the billing page, for Owners and Admins. See [Billing](https://docs.filone.com/app/billing). ## Deleting an organization -Not available in the console yet. The Danger zone on the Edit organization page -(Owners only) points to support@filone.com: email them to delete the organization. +Deleting an organization is not available in the console yet. The **Danger zone** on the **Edit organization** page, shown to Owners only, points you to [support@filone.com](mailto:support@filone.com): email them to delete the organization. --- @@ -2142,109 +2312,100 @@ Not available in the console yet. The Danger zone on the Edit organization page Source: https://docs.filone.com/app/billing -Console-specific. Trial lifecycle, pricing model and measurement live on Trial & -Billing, Pricing and Usage. +Billing is a page of its own, at `/billing`. Open it from **Billing** in the **Organization** group of the left sidebar (see [Where to find the organization's pages](https://docs.filone.com/app/organization#where-to-find-the-organizations-pages)). + +Billing is visible to **Owners** and **Admins**. Every action on it (choosing or changing a plan, adding or updating a card, opening the Stripe portal) is for **Owners** only, so an Admin sees the same figures without the buttons. Members and Read only users see "Billing is managed by your organization's owners and admins" instead. See [Roles and permissions](https://docs.filone.com/app/organization#roles-and-permissions). -BILLING IS ITS OWN PAGE, at /billing, opened from "Billing" in the organization -menu at the top of the left sidebar. +This page covers the console specifically. For the trial lifecycle, the pricing model, and how usage is measured, see [Trial & Billing](https://docs.filone.com/billing/trial), [Pricing](https://docs.filone.com/billing/pricing), and [Usage](https://docs.filone.com/billing/usage). -VISIBLE TO OWNERS AND ADMINS. Every action on it (choosing or changing a plan, -adding or updating a card, opening the Stripe portal) is OWNER-ONLY, so an Admin -sees the same figures without the buttons. Members and Read only users see -"Billing is managed by your organization's owners and admins" instead. +## Your plan -## Plan card +The **Plan** card names your plan and carries a status badge: | Status | Badge | Plan name and detail line | |--------|-------|---------------------------| -| Trial | Trial | "Free trial", days until the trial ends (storage and egress limits are on the usage card) | -| Paid | Active | "Pay as you go", per-TB rate, renewal date | -| Payment failed | Payment failed (amber) | Plan name, rate, renewal date, as for a paid plan | -| Grace period | Grace period | Plan name and rate, days until access ends | -| Canceled | Canceled | Plan name and rate, date it was canceled | -| No plan | None | "No plan", "Choose a plan to start storing data" | +| Trial | **Active** (blue) | **Free trial**. The trial's storage and egress limits are on the [usage card](#usage) | +| Paid | **Active** (green) | **Pay as you go**, with your per-TB rate and the renewal date | +| Billed manually | **Active** (green) | The name on your agreement, or **Custom plan**, with **Billed manually** | +| Payment failed | **Payment failed** (amber) | Your plan name, rate, and renewal date, as for a paid plan | +| Grace period | **Grace period** | Your plan name and rate, and how many days until access ends | +| Canceled | **Canceled** | Your plan name and rate, and the date it was canceled | +| No plan | None | **No plan**, with **Choose a plan to start storing data** | -A plan set up with the sales team shows the name on your agreement, and "Custom -pricing" where there is no single per-TB rate. +If your plan was set up with the sales team, the card shows the name on your agreement, and **Custom pricing** where there is no single per-TB rate to show. An organization billed manually by the sales team has no payment method to manage in the console. -Button: "Upgrade" on trial, "Manage plan" on a paid plan (INCLUDING ONE WHOSE -PAYMENT FAILED), "Reactivate" once canceled, "Choose a plan" during the grace -period or with no plan. +The button in this card is **Upgrade** on the trial, **Manage plan** on a paid plan (including one whose payment failed), **Reactivate** once the subscription is canceled, and **Choose a plan** during the grace period or with no plan. -Banners above the cards: "Your last payment failed" (button "Update payment"); -"This organization is read-only" (grace period; "Choose a plan"); "This -subscription is canceled" ("Reactivate"). +A canceled subscription can be restarted at any time: an Owner clicks **Reactivate**, and the banner confirms "Your data is still here." Access returns as soon as the new subscription starts, without contacting support. -A FAILED PAYMENT MAKES THE DASHBOARD READ-ONLY. Check the banner and update the -payment method to resume. +A banner above the cards flags a problem with the account: + +| Banner | Button | +|--------|--------| +| **Your last payment failed** | **Update payment** | +| **This organization is read-only** (grace period) | **Choose a plan** | +| **This subscription is canceled** | **Reactivate** | + +Note: A failed payment makes the dashboard read-only +When a payment fails, the dashboard becomes read-only. Check the banner and update your payment method to resume. See [Trial & Billing](https://docs.filone.com/billing/trial). ## Usage -Headed "Usage during your trial" on the trial and "Usage this billing period" -otherwise, with the period dates and days left. +The usage card is headed **Usage during your trial** on the trial and **Usage this billing period** otherwise, with the dates of the period and how many days are left. + +**Storage** always appears. On the trial it is shown against the 1 TB cap with a progress bar; on a paid plan there is no cap, so you see the figure alone. + +**Egress** also always appears. On the trial it is shown against the 2 TB cap with a progress bar. On a paid plan it is labelled **Free**, since there are no egress fees. -"Storage" always appears: against the 1 TB cap with a progress bar on trial, -figure alone on paid (no cap). "Egress" also always appears: against the 2 TB cap -with a progress bar on trial, labelled "Free" on paid (no egress fees). -"Estimated total" appears on a paid plan with a per-TB rate; where the monthly -minimum is higher than usage, it shows the minimum, captioned "Your monthly -minimum". Plans with custom pricing show no estimate, and the card says the total -for the period is in Stripe. +**Estimated total** appears on a paid plan with a per-TB rate. Where your monthly minimum is higher than your usage, the estimate shows the minimum, captioned **Your monthly minimum**. Plans with custom pricing show no estimate, and the card says the total for the period is in Stripe. -THE ESTIMATE IS A GUIDE, NOT THE INVOICE: it applies your plan's per-TB rate to -the most recent storage reading with the monthly minimum as the floor, while the -invoice uses AVERAGE storage across the billing period. The estimate excludes -egress. Sizes are decimal (1 TB = 1,000 GB). +Info: How the estimate is calculated +The estimate applies your plan's per-TB rate to your most recent storage reading, with your monthly minimum as the floor. Your invoice is calculated from your average storage across the billing period, so treat the estimate as a guide to where you are heading rather than the final figure. Egress is not included, since it is free on paid plans. + +Sizes here are decimal: 1 TB means 1,000 GB. See [Usage](https://docs.filone.com/billing/usage). ## Payment method +The **Payment method** card shows one of three things: + | What you see | Button | |--------------|--------| -| "No card on file", "Needed before your trial ends" | Add card | -| Card brand and last four digits, with expiry date | Update | -| "Billed by invoice" (paid plan with no card on file) | Manage | +| **No card on file**, "Needed before your trial ends" | **Add card** | +| The card brand and last four digits, with the expiry date | **Update** | +| **Billed by invoice**, for a paid plan with no card on file | **Manage** | -"Update", "Manage" and "Manage plan" open the STRIPE CUSTOMER PORTAL, where card -details are entered and stored; FIL ONE DOES NOT HOLD THE CARD NUMBER. +**Update**, **Manage**, and **Manage plan** open the Stripe customer portal, where the card details are entered and stored. Fil One does not hold your card number. -CANCELLATION IS HANDLED IN THE STRIPE PORTAL, via "Manage plan". +Note: Cancelling +Cancellation is handled in the Stripe portal, reached through **Manage plan**, so only Owners can cancel. ## Choosing a plan -"Add card", "Upgrade", "Choose a plan" and "Reactivate" open "Choose your plan", -with two plans: -- "Pay as you go": $5.99 per TB per month, $5.99 monthly minimum, no egress fees, - no API request fees. "Upgrade now" goes to the payment form. -- "Business plan": "Custom pricing", purchased in 1, 3, or 5-year increments, - with capacity assurance and deployment SLAs. "Contact sales team" opens a sales - contact form. +**Add card**, **Upgrade**, **Choose a plan**, and **Reactivate** open **Choose your plan**, which offers two plans: + +- **Pay as you go**, at **$5.99** per TB per month with a $5.99 monthly minimum, no egress fees, and no API request fees. **Upgrade now** takes you to the payment form. +- **Business plan**, with **Custom pricing**, purchased in 1, 3, or 5-year increments, with capacity assurance and deployment SLAs. **Contact sales team** opens a sales contact form. + +The payment form takes your card number, expiry, and CVC. **Start subscription** activates the plan. -The payment form takes card number, expiry, and CVC. "Start subscription" -activates the plan. -When reactivating with a card already on file, the Pay as you go button reads -"Reactivate" and uses that card, with a "Use a different card" link. +If you are reactivating and a card is already on file, the **Pay as you go** button reads **Reactivate** and uses that card, with a **Use a different card** link if you would rather enter a new one. ## Invoices -Date, status, amount and a "PDF" link per invoice. Statuses: Paid, Due, Void, -Unpaid. Not shown during the trial or with no plan; before the first invoice it -reads "No invoices yet". Shows the 12 MOST RECENT ISSUED INVOICES, INCLUDING ANY -STILL UNPAID; drafts are not shown. "View all" opens the Stripe portal for full -history and appears for Owners only. +The **Invoices** list shows the date, status, amount, and a **PDF** link for each invoice. Statuses are **Paid**, **Due**, **Void**, and **Unpaid**. + +Three things to expect: + +- The list does not appear during the trial or with no plan. Before your first invoice it reads **No invoices yet**. +- It shows your 12 most recent issued invoices, including any that are still unpaid. Drafts are not shown. +- **View all** opens the Stripe portal for your full billing history. It appears for Owners only. ## Need help? -The panel beside the cards offers "Billing questions" (links to "Contact -support" for invoice, payment, or plan questions). On the trial or with no plan, -it also offers "Volume pricing", where "Talk to sales" opens the sales contact -form. +The panel beside the cards offers **Billing questions**, which links to **Contact support** for questions about an invoice, a payment, or your plan. On the trial or with no plan, it also offers **Volume pricing**, where **Talk to sales** opens the sales contact form. -EARLIER SUBSCRIBERS KEEP THEIR TERMS: organizations that subscribed before the -move to $5.99 keep $4.99 per TB with a $4.99 monthly minimum, or, for accounts -created before any minimum was introduced, per-unit pricing with no minimum. The -plan card and estimate use your own rate and minimum. The "Choose your plan" -dialog always shows the current $5.99 wording, so the plan card is authoritative -per account. +Note: If your account predates the current price +Organizations that subscribed before the move to $5.99 keep their earlier terms: $4.99 per TB with a $4.99 monthly minimum, or, for accounts created before any minimum was introduced, per-unit pricing with no minimum. The plan card and the estimate use your own rate and minimum. The **Choose your plan** dialog always shows the current $5.99 wording, so take the plan card as the guide to your own terms. See [Pricing](https://docs.filone.com/billing/pricing). --- @@ -2253,63 +2414,47 @@ per account. Source: https://docs.filone.com/app/settings -In the user menu at the bottom of the left sidebar: profile, the organizations -you belong to, notification preferences and account security. Every member of an organization has their own Settings. +**Settings** is in the user menu at the bottom of the left sidebar. It holds your profile, the organizations you belong to, your notification preferences, and your account security. Every member of an organization has their own Settings. ## Profile -| Field | Rules | -|-------|-------| -| Full name | Cannot be empty, up to 200 characters | -| Email | Must be a valid address; disposable addresses are rejected | +The **Profile** card holds your **Avatar**, **Name**, and **Email**. + +- **Avatar**: upload a picture. It saves as soon as it uploads. +- **Name**: up to 200 characters, and can't be empty. It saves on its own when you click out of the field. There is no save button. +- **Email**: click the field to open **Change email**, enter the **New email**, and click **Update**. Disposable addresses are rejected. -"Save changes" is disabled until a field is edited, and a note beside it lists -what will be saved. +Warning: Changing your email address sends you back through verification +Updating the address marks the account unverified, sends a verification email to the new address, and drops you straight onto the verification screen. Every page redirects there until you confirm, exactly as for a new account. -CHANGING THE EMAIL ADDRESS RESETS VERIFICATION. Saving a new address marks the -account unverified, sends a verification email to the new address, and lands on -the verification screen; every page redirects there until it is confirmed, as for -a new account. The address can be edited again while unverified, so a typo is -recoverable. +You can change the address again while unverified, so a typo is recoverable. -GOOGLE AND GITHUB SIGN-INS MANAGE NAME AND EMAIL AT THE PROVIDER. Both fields are -read-only in Fil One, labelled "Managed by Google" / "Managed by GitHub" with a -link to that provider's profile page. +**If you signed in with Google or GitHub, your name and email are managed there.** Avatar, name, and email are read-only for social sign-ins, labelled *Managed by Google* or *Managed by GitHub* with a link straight to that provider's profile page, so you keep one source of truth for them. -The profile holds only Full name and Email: the organization's name is not part -of your profile. Owners and Admins rename it on the "Edit organization" page, -from the organization menu at the top of the sidebar (2 to 100 characters, -letters, numbers, spaces, hyphens, periods only). +Your organization's name is not part of your profile. Owners and Admins rename it on the **Edit organization** page, opened from the organization menu at the top of the left sidebar, where the name must be 2 to 100 characters, using letters, numbers, spaces, hyphens, and periods only. ## Organizations -Lists every organization you belong to, with your role and when you joined. Each -row's menu offers "Switch to this organization" and "Leave organization". -Leaving removes your access and you can only rejoin with a new invitation; the -last Owner of an organization can't leave it. +The **Organizations** section lists every organization you belong to, with your role and when you joined. Each row's menu offers **Switch to this organization** and **Leave organization**. Leaving removes your access to that organization and everything in it, and you can only rejoin with a new invitation. The last Owner of an organization can't leave it. See [Organization](https://docs.filone.com/app/organization#leaving-an-organization). ## Notifications -"Marketing emails" ("Receive updates about new features") is a working toggle: it -reflects the current subscription status, is off until turned on, and saves on -flip with no Save button. +**Marketing emails** ("Receive updates about new features") is a working toggle. It reflects your current subscription status, is off until you turn it on, and saves as soon as you flip it. -THERE IS NO NOTIFICATION SETTING FOR UPLOADS OR STORAGE LIMITS. Direct users to -the Dashboard usage cards to track storage and egress against the trial caps, -where reaching a cap changes what the account can do. +Note: Keep an eye on the trial caps +There is no notification setting for uploads or storage limits. Keep an eye on the usage cards on the [Dashboard](https://docs.filone.com/app/dashboard), which show your storage and egress against the trial caps. This is worth doing during the trial, where reaching a cap changes what the account can do. See [Usage](https://docs.filone.com/billing/usage). ## Security -Two-factor authentication, passkeys, recovery codes and password changes are all -under Settings > Security (see Account Security). Password is managed by the -provider on Google and GitHub accounts, so no Change button appears. +Two-factor authentication, passkeys, recovery codes, and password changes all live in Settings under **Security**. Password is managed by your provider on Google and GitHub accounts, so no **Change** button appears. + +See [Account Security](https://docs.filone.com/security/account-security) for the full walkthrough. ## Danger zone -The last card on the page is "Danger zone", with "Delete account". NOT -SELF-SERVICE: the card asks you to email support@filone.com to delete your account. -Deleting an organization is separate and is covered on the Edit organization -page. +The last card on the page is **Danger zone**, with **Delete account**. Deleting your account is not available in the console yet: the card asks you to email [support@filone.com](mailto:support@filone.com), and the team will take it from there. + +Deleting an organization is separate, and is covered on the **Edit organization** page. See [Deleting an organization](https://docs.filone.com/app/organization#deleting-an-organization). --- @@ -2318,34 +2463,30 @@ page. Source: https://docs.filone.com/app/support -Reached from the USER MENU at the bottom of the left sidebar (your name and -avatar), which offers "Settings", "Support", "Documentation" and "Log out". -"Support" opens the support form. (There is no separate Help menu any more.) +**Support** and **Documentation** are at the bottom of the left sidebar, above your name. **Support** opens the support page. + +## The support page -## The form +The page is headed **Support**, with "We typically respond within 1 business day" underneath. It has two fields: + +| Field | Notes | +|-------|-------| +| **Category** | **Product issue**, **Billing issue**, **General inquiry**, or **Feature request** | +| **Message** | What you need help with | -Headed "Talk to an expert", stating a typical response within one business day. -All fields required: First name, Last name, Company name, Email (the reply -address), Category, Message. Category options: "Product Issue", "Billing Issue", -"General Inquiry", "Feature Request". +You don't enter your name, organization, or email: the console sends them with your message from your account. Under the form, "We'll reply to" shows the address the answer goes to. An **Email** field appears only if your account has no email address. Click **Send message**. The form clears and confirms that the team will get back to you within 1 business day. -The form starts empty rather than pre-filling from the signed-in account, so the -email entered is where the reply goes. Submitting clears the form and confirms a -reply within one business day. +Note: Where the reply arrives +Your message creates a ticket for the support team, and they reply by email to your account's address. Look for the reply in your inbox, not in the console. -REPLIES ARRIVE BY EMAIL. The message creates a ticket for the support team; the -console does not show a ticket list or status view. +Below the form, **Common questions** answers a few frequent questions, such as whether buckets can be made public. The **More help** panel beside it links to these docs and offers **Report a bug**. ## Other routes -- "Documentation" in the same user menu opens the docs in a new tab. -- The system status indicator links to the Fil One status page, the quickest - check for whether an issue is already known. On desktop it is in the bar along - the bottom of the content area; on a phone it is in the sidebar drawer. -- Account deletion is handled by email at support@filone.com. -- Volume pricing, SLAs and the Business plan go through "Contact sales team" in - the "Choose your plan" dialog on Billing. On the trial or with no plan, "Talk to - sales" in the "Need help?" panel beside the billing cards does the same. +- **Documentation** at the bottom of the left sidebar opens these docs in a new tab. +- The system status indicator links to the Fil One status page, which is the quickest way to check whether an issue is already known. On desktop it sits in the bar along the bottom of the content area; on a phone it is in the sidebar drawer. +- Account deletion is handled over email at [support@filone.com](mailto:support@filone.com), as noted in [Settings](https://docs.filone.com/app/settings). +- For volume pricing, SLAs, or the Business plan, **Contact sales team** in the **Choose your plan** dialog on [Billing](https://docs.filone.com/app/billing) reaches the sales team directly. On the trial or with no plan, **Talk to sales** in the **Need help?** panel beside the billing cards does the same. --- @@ -2356,31 +2497,37 @@ Source: https://docs.filone.com/reference/overview ## Base endpoint -``` -https://s3.eu-west-1.filonecontent.com -``` +The endpoint is region-specific. Use the one for the region your bucket is in: -All requests must use HTTPS and authenticate with AWS Signature Version 4 (SigV4). +| Region | Endpoint | +|--------|----------| +| Europe (France) `eu-west-1` (default) | `https://s3.eu-west-1.filonecontent.com` | +| US East (Michigan) `us-east-1` | `https://s3.us-east-1.filonecontent.com` | + +All requests must use HTTPS and authenticate with AWS Signature Version 4 (SigV4). Examples on this page and elsewhere in the docs use `eu-west-1` because it is the default region — substitute your own where it differs. Access keys are scoped to a single region and must match the endpoint you call. ## Request format -Use path-style addressing: +Fil One accepts standard S3 API requests. Use path-style addressing: -``` +```text +# Path style https://s3.eu-west-1.filonecontent.com/my-bucket/my-key ``` -Virtual-hosted-style URLs (https://my-bucket.s3..filonecontent.com/my-key) are not supported. -Configure your S3 client to use path-style requests: -- boto3: set `config=Config(s3={"addressing_style": "path"})` — path-style is NOT the default, even with a custom endpoint, and requests fail without it -- AWS CLI: set `s3.addressing_style = path` in the profile (or `aws configure set default.s3.addressing_style path`) -- AWS SDK JS v3: set `forcePathStyle: true` -- Go aws-sdk-go-v2: set `UsePathStyle: true` +Virtual-hosted-style URLs (`https://my-bucket.s3..filonecontent.com/my-key`) are not supported. Configure your S3 client to use path-style requests (see [SDK guides](https://docs.filone.com/sdk/overview)). + +## Authentication + +Include SigV4 authentication headers in every request. All S3-compatible SDKs handle this automatically when you provide your access key and secret key. See [Authentication](https://docs.filone.com/security/authentication) for setup instructions. ## Response format -Standard S3 conventions — XML for list and error responses, raw bytes for object -data. Standard S3 headers included (x-amz-request-id, ETag, Content-Length, etc.). +Responses follow standard S3 conventions -- XML for list and error responses, raw bytes for object data. All responses include standard S3 headers (`x-amz-request-id`, `ETag`, `Content-Length`, etc.). + +## Supported operations + +See the [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility) page for the full list of supported operations. --- @@ -2389,197 +2536,263 @@ data. Standard S3 headers included (x-amz-request-id, ETag, Content-Length, etc. Source: https://docs.filone.com/reference/s3-compatibility -Fil One provides an S3-compatible API. Point your SDK or CLI at the Fil One -endpoint and authenticate with your API keys. +Fil One provides an S3-compatible API. It works with standard S3 SDKs and tools once you set the endpoint and enable path-style addressing; see the gaps below. Authenticate with your [API keys](https://docs.filone.com/security/api-keys). + +## Endpoint + +Endpoints are region-specific. Use the endpoint for the region your bucket lives in: + +| Region | Endpoint | +|--------|----------| +| Europe (France) `eu-west-1` (default) | `https://s3.eu-west-1.filonecontent.com` | +| US East (Michigan) `us-east-1` | `https://s3.us-east-1.filonecontent.com` | + +All requests use HTTPS. HTTP connections are rejected. -## Connection parameters +## Authentication + +Fil One supports **AWS Signature Version 4 (SigV4)** authentication. Any S3 client or SDK that supports SigV4 will work without modification. | Parameter | Value | |-----------|-------| -| Endpoint | https://s3..filonecontent.com — region-specific | -| Region | eu-west-1 (Europe, France, default) or us-east-1 (US East, Michigan) | +| Endpoint | `https://s3..filonecontent.com` | +| Region | `eu-west-1` or `us-east-1` | | Signature version | SigV4 | | Path style | Required | | Virtual-hosted style | Not supported | ## Supported operations -Numeric limits quoted below (5 TB max object, 5 GB single-PUT, 5 MB/5 GB part -sizes, 10,000 parts, 1,000-object bulk delete) are standard AWS S3 values, not -independently confirmed for Fil One. +Note: About the numeric limits below +Specific size and count limits quoted in this table (5 TB max object, 5 GB single-PUT, 5 MB / 5 GB part sizes, 10,000 parts, 1,000-object bulk delete) are the **standard AWS S3 values**. Fil One's storage gateway is expected to follow them, but they have not been independently confirmed — see [Limits](https://docs.filone.com/limits). + +Warning: How unsupported operations respond in `eu-west-1` +In `eu-west-1`, operations that Fil One does not implement return **`AccessDenied` (HTTP 403)**, not `NotImplemented` (501). This is confirmed by a compatibility test run against the region. -⚠️ IN eu-west-1, UNIMPLEMENTED OPERATIONS RETURN AccessDenied (403), NOT -NotImplemented (501). Confirmed by a compatibility test run against the region. A -403 from PutBucketVersioning, PutBucketPolicy, PutBucketAcl, PutBucketEncryption, -PutBucketLifecycleConfiguration or the tagging operations means THE FEATURE IS -ABSENT, not that the access key lacks a permission. Do not send customers to -audit key scopes for these. Code that branches on NotImplemented to degrade -gracefully must treat 403 on these operations the same way. +A 403 from `PutBucketPolicy`, `PutBucketAcl`, `PutBucketLifecycleConfiguration`, or the tagging operations means *the feature is absent*, not that your key lacks a permission. Bucket-configuration calls such as `PutBucketVersioning` and `PutBucketEncryption` can't be granted to any key, so they fail the same way. Don't spend time auditing your access-key scopes for these. Code that branches on `NotImplemented` to degrade gracefully needs to treat 403 on these operations the same way. ### Bucket operations | Operation | Status | Notes | |-----------|--------|-------| -| CreateBucket | Region-dependent | Supported in us-east-1. Not available in eu-west-1 — use the dashboard. | -| DeleteBucket | Region-dependent | Supported in us-east-1 (bucket must be empty). Not available in eu-west-1. | -| ListBuckets | Supported | | -| HeadBucket | Supported | | -| GetBucketVersioning | Supported | Returns Enabled for versioned buckets; Suspended is never returned. | -| PutBucketVersioning | Region-dependent | REJECTED with AccessDenied in eu-west-1 for enable as well as suspend — versioning there is set at bucket creation and cannot be changed over the API at all. In us-east-1 accepted for SDK compatibility, but still cannot be suspended once enabled. | -| GetBucketObjectLockConfiguration / PutBucketObjectLockConfiguration | Supported | Sets the bucket-level default retention (Governance or Compliance, 1 day to 100 years). Object Lock requires versioning; both are set at bucket creation only. | -| GetBucketEncryption | Region-dependent | Supported in us-east-1. Returns AccessDenied in eu-west-1, so no configuration can be read back there. Encryption is on regardless. | -| PutBucketEncryption | Region-dependent | REJECTED with AccessDenied in eu-west-1, even for a valid SSE-S3 default rule. Accepted but ineffective in us-east-1. Encryption cannot be modified or disabled in either region. | -| DeleteBucketEncryption | Not supported | AccessDenied in eu-west-1. Encryption cannot be disabled. | -| Bucket ACLs, bucket policies, lifecycle rules, event notifications, bucket tagging | Not supported | All return AccessDenied in eu-west-1. See "Not yet supported" below. | -| GetBucketLogging / PutBucketLogging | Not supported | Server access logging is not implemented. PutBucketLogging returns MalformedXML in eu-west-1 even for a well-formed body. | -| GetPublicAccessBlock / PutPublicAccessBlock | Not supported | Public access is never permitted, so there is no block configuration. PutPublicAccessBlock returns MalformedXML in eu-west-1 even for a well-formed body. | +| `CreateBucket` | ⚠️ Region-dependent | Supported in `us-east-1`. Not available in `eu-west-1` — create buckets there via the dashboard. | +| `DeleteBucket` | ⚠️ Region-dependent | Supported in `us-east-1` (the bucket must be empty). Not available in `eu-west-1`. | +| `ListBuckets` | ✅ Supported | | +| `HeadBucket` | ✅ Supported | | +| `GetBucketVersioning` | ✅ Supported | Returns `Enabled` for versioned buckets, `Suspended` is never returned. | +| `PutBucketVersioning` | ❌ Not available to access keys | No access key can be granted this action, in either region. Versioning is set when you create the bucket in the console and cannot be changed afterwards. | +| `GetBucketObjectLockConfiguration` | ✅ Supported | Returns the bucket-level default retention policy, if set. | +| `PutBucketObjectLockConfiguration` | ❌ Not available to access keys | No access key can be granted this action, in either region. Object Lock and the default retention are set when you create the bucket in the console. | +| `GetBucketEncryption` | ❌ Not available to access keys | No access key can be granted this action, in either region. Encryption is always on. | +| `PutBucketEncryption` | ❌ Not available to access keys | No access key can be granted this action, in either region. Encryption cannot be modified or disabled. | +| `DeleteBucketEncryption` | ❌ Not supported | Rejected with `AccessDenied` in `eu-west-1`. Encryption cannot be disabled. | +| `GetBucketAcl` | ❌ Not supported | ACL model is not implemented. Returns `AccessDenied` in `eu-west-1`. See [ACLs](#acls). | +| `PutBucketAcl` | ❌ Not supported | ACL model is not implemented. Rejected with `AccessDenied` in `eu-west-1`. | +| `GetBucketPolicy` | ❌ Not supported | Bucket policies are not implemented. | +| `PutBucketPolicy` | ❌ Not supported | Bucket policies are not implemented. Rejected with `AccessDenied` in `eu-west-1`. | +| `GetBucketLifecycleConfiguration` | ❌ Not supported | Planned for a future release. | +| `PutBucketLifecycleConfiguration` | ❌ Not supported | Planned for a future release. Rejected with `AccessDenied` in `eu-west-1`. | +| `GetBucketNotificationConfiguration` | ❌ Not supported | Event notifications are not supported. | +| `PutBucketNotificationConfiguration` | ❌ Not supported | Event notifications are not supported. | +| `GetBucketTagging` | ❌ Not supported | Bucket and object tagging are not implemented. | +| `PutBucketTagging` | ❌ Not supported | Bucket and object tagging are not implemented. | +| `GetBucketLogging` | ❌ Not supported | Server access logging is not implemented. | +| `PutBucketLogging` | ❌ Not supported | Rejected in `eu-west-1` (`MalformedXML`, even for a well-formed configuration). | +| `GetPublicAccessBlock` | ❌ Not supported | Public access is never permitted, so there is no block configuration to read. | +| `PutPublicAccessBlock` | ❌ Not supported | Rejected in `eu-west-1` (`MalformedXML`, even for a well-formed configuration). All buckets are private unconditionally. | ### Object operations | Operation | Status | Notes | |-----------|--------|-------| -| PutObject | Supported | Max 5 TB (use multipart for > 5 GB). | -| GetObject | Supported | Supports Range requests and a VersionId to retrieve a specific version. | -| DeleteObject / DeleteObjects | Supported | Bulk delete up to 1,000 objects per request. Creates a delete marker on versioned buckets; pass VersionId to permanently delete a specific version. | -| HeadObject | Supported | | -| ListObjectsV2 | Supported | | -| ListObjectVersions | Supported | Returns all versions and delete markers. | -| CopyObject | Region-dependent | Confirmed working in us-east-1, including copying a specific VersionId onto the current key (version restore — promotes an older version to current). In eu-west-1 PLAIN COPY WORKS (most copy tests pass a compatibility run) but the VERSION-ID FORM IS UNVERIFIED there, because the harness cannot configure versioning over the API. Verify before relying on it; download and re-upload is the fallback. | -| GetObjectRetention | Supported | Returns the Object Lock retention for a specific version. | -| PutObjectRetention | Supported | Both regions. Set, extend, or shorten a version's retention (shortening uses S3's standard bypass-governance-retention mechanism, which is a protocol feature of the gateway, NOT a Fil One access-key permission). Requires the matching granular access-key permission. | -| GetObjectLegalHold / PutObjectLegalHold | Supported | Both regions, including blocking delete while a hold is active — requires the matching access-key permission. | -| GetObjectAttributes | Not supported | AccessDenied in eu-west-1. Use HeadObject for size, ETag and metadata. | -| Object ACLs, object tagging | Not supported | Dedicated calls (GetObjectAcl, PutObjectAcl, GetObjectTagging, PutObjectTagging) return AccessDenied in eu-west-1. A canned-ACL HEADER on an upload is a different case: it is SILENTLY IGNORED and the upload SUCCEEDS. See ACLs below. | -| RestoreObject | Not applicable | Single storage class — no archival tiers to restore from. | -| SelectObjectContent | Not planned | S3 Select is not planned. | +| `PutObject` | ✅ Supported | Max object size: 5 TB (use multipart for objects > 5 GB). | +| `GetObject` | ✅ Supported | Supports range requests (`Range` header). Supports `VersionId` to retrieve a specific version. | +| `DeleteObject` | ✅ Supported | Creates a delete marker on versioned buckets. Pass `VersionId` to permanently delete a specific version. | +| `DeleteObjects` | ✅ Supported | Bulk delete up to 1,000 objects per request. | +| `HeadObject` | ✅ Supported | | +| `ListObjectsV2` | ✅ Supported | | +| `ListObjectVersions` | ✅ Supported | Returns all versions and delete markers. Supports `Prefix` and `KeyMarker` filters. | +| `CopyObject` | ⚠️ Region-dependent | Confirmed working in `us-east-1`, including copying a specific `VersionId` onto the current key. In `eu-west-1`, most copy operations pass a compatibility run, so plain server-side copy works there, but **copying a specific `VersionId` is not yet confirmed** in that region. Verify a version-promote copy against your own bucket before relying on it. | +| `GetObjectRetention` | ✅ Supported | Returns the Object Lock retention for a specific version. | +| `PutObjectRetention` | ✅ Supported | Set or extend a version's retention. Retention can't be shortened, because no key can be granted the bypass-governance permission. Requires the **Set retention** permission (Owner-only to grant). | +| `GetObjectLegalHold` | ✅ Supported | Requires the matching access-key permission. | +| `PutObjectLegalHold` | ✅ Supported | Blocks delete while a hold is active. Requires the **Set legal hold** permission (Owner-only to grant). | +| `GetObjectAttributes` | ❌ Not supported | Returns `AccessDenied` in `eu-west-1`. Use `HeadObject` for size, ETag, and metadata instead. | +| `GetObjectAcl` | ❌ Not supported | ACL model is not implemented. Returns `AccessDenied` in `eu-west-1`, including on objects uploaded with a canned-ACL header. | +| `PutObjectAcl` | ❌ Not supported | ACL model is not implemented. Rejected with `AccessDenied` in `eu-west-1`. | +| `GetObjectTagging` | ❌ Not supported | Object tagging is not implemented. Returns `AccessDenied` in `eu-west-1`. | +| `PutObjectTagging` | ❌ Not supported | Object tagging is not implemented. Rejected with `AccessDenied` in `eu-west-1`. | +| `RestoreObject` | ❌ Not applicable | Fil One has a single storage class. There are no archival tiers to restore from. | +| `SelectObjectContent` | ❌ Not planned | S3 Select is not planned. | ### Multipart upload -Supported through the S3 API in all regions: CreateMultipartUpload, UploadPart -(5 MB–5 GB parts), CompleteMultipartUpload (max 10,000 parts), -AbortMultipartUpload, ListParts, ListMultipartUploads. Dashboard uploads -always use a single PutObject, so browser uploads are bounded by the -single-PUT ceiling — use the S3 API or CLI for larger objects. +Multipart upload is supported through the S3 API in **all regions**. Note that uploads from the Fil One **dashboard** always use a single `PutObject` request, so browser uploads are bounded by the single-PUT ceiling — use the S3 API or CLI for larger objects. + +| Operation | Status | Notes | +|-----------|--------|-------| +| `CreateMultipartUpload` | ✅ Supported | | +| `UploadPart` | ✅ Supported | Minimum part size: 5 MB (except last part). Maximum: 5 GB. | +| `CompleteMultipartUpload` | ✅ Supported | Maximum 10,000 parts per upload. | +| `AbortMultipartUpload` | ✅ Supported | | +| `ListParts` | ✅ Supported | | +| `ListMultipartUploads` | ✅ Supported | | ### Versioning -Opt-in, set at bucket creation only, cannot be suspended once enabled. The -dashboard has no restore/roll-back/"make current" action; in us-east-1 you can -promote an older version via CopyObject (see above). In eu-west-1 plain copy works -but the version-id form is unverified, so test it before relying on it. +Versioning is **opt-in** and configured at bucket creation time. Once enabled on a bucket, it cannot be suspended or disabled. Every upload to an existing key on a versioned bucket creates a new version rather than overwriting. + +| Operation | Status | Notes | +|-----------|--------|-------| +| `GetBucketVersioning` | ✅ Supported | Returns `Enabled` for versioned buckets. | +| `ListObjectVersions` | ✅ Supported | Lists all versions and delete markers in a bucket. | +| `GetObject` with `VersionId` | ✅ Supported | Retrieves a specific historical version by ID. | +| `DeleteObject` with `VersionId` | ✅ Supported | Permanently deletes a specific version, bypassing delete markers. | +| `PutBucketVersioning` | ❌ Not available to access keys | Versioning is set at bucket creation and cannot be suspended or changed. | +| `CopyObject` with `x-amz-copy-source-version-id` | ⚠️ Region-dependent | Confirmed working in `us-east-1` — copy a specific version onto the current key to promote it. Not yet confirmed in `eu-west-1`: plain copy works there, but the version-id form has not been tested. | + +The Fil One **dashboard** has no restore, roll-back, or "make current" action — you can list, download, and delete any prior version there, but not promote one to current. In `us-east-1`, you can promote an older version via the API with `CopyObject` (see above). In `eu-west-1`, plain server-side copy works but the version-id form is unverified, so test it against your own bucket first and fall back to downloading the version and uploading it again if it fails. + +See [Versioning](https://docs.filone.com/storage/versioning) for detailed usage and examples. ### Object Lock -WORM protection; requires versioning; both Governance (default) and -Compliance modes supported, set at bucket creation only. OBJECT LOCK, RETENTION AND -LEGAL HOLD WORK IN BOTH REGIONS. The evidence differs by region: us-east-1 is -covered by the automated compatibility suite (39/39 object-lock tests), eu-west-1 -was verified by ENGINEERING TESTING rather than that suite, because the harness -could not create an Object-Lock-enabled bucket there to test against (a limitation -of the test setup, NOT a product gap). Do not describe Object Lock as unverified or -risky in eu-west-1. In standard S3, -Governance retention can be overridden by a caller with the bypass -permission, but Fil One does not currently expose a grantable bypass -permission, so treat Governance objects as protected for their retention -period in practice. +Object Lock enforces WORM (Write-Once-Read-Many) protection. Both Governance and Compliance mode are supported. Object Lock requires versioning, and both are set at bucket creation time. + +Note: Where the evidence comes from +Object Lock, retention, and Legal Hold are verified in **both** regions: by an automated compatibility suite in `us-east-1`, and by engineering testing in `eu-west-1`. + +| Operation | Status | Notes | +|-----------|--------|-------| +| `GetBucketObjectLockConfiguration` | ✅ Supported | Returns the bucket-level default retention policy. | +| `PutBucketObjectLockConfiguration` | ❌ Not available to access keys | The default retention (Governance or Compliance, 1 day – 100 years) is set when you create the bucket in the console. | +| `GetObjectRetention` | ✅ Supported | Returns the retention setting for a specific object version. | +| `PutObjectRetention` | ✅ Supported | Set or extend a retention period. It can't be shortened: no key can be granted the bypass-governance permission. Requires the **Set retention** permission (Owner-only to grant). | +| `GetObjectLegalHold` | ✅ Supported | Requires the matching access-key permission. | +| `PutObjectLegalHold` | ✅ Supported | Blocks delete while a hold is active. Requires the **Set legal hold** permission (Owner-only to grant). | + +**Object Lock modes:** + +| Mode | Status | +|------|--------| +| Governance | ✅ Supported — the default when you enable Object Lock. In standard S3, Governance retention can be overridden by a caller with the bypass permission, but **Fil One does not currently expose a grantable bypass permission**, so treat Governance objects as protected for their retention period in practice. | +| Compliance | ✅ Supported — no user, including the organization Owner, can delete a locked object or shorten its retention. | + +See [Object Lock](https://docs.filone.com/storage/object-lock) for compliance use cases, retention configuration, and examples. + +### Presigned URLs + +| Operation | Status | Notes | +|-----------|--------|-------| +| Presigned `GetObject` | ✅ Supported | Generate time-limited download URLs without requiring API credentials. | +| Presigned `PutObject` | ✅ Supported | Generate time-limited upload URLs for direct client or browser uploads. With the AWS SDK for JavaScript v3.729 or later, set `requestChecksumCalculation: "WHEN_REQUIRED"` on the client, or the upload fails with `BadDigest`. See [JavaScript](https://docs.filone.com/sdk/javascript#presigned-urls). | + +### Server-side encryption + +Encryption is **always enabled** on every Fil One bucket. There is nothing to configure. + +| Feature | Status | Notes | +|---------|--------|-------| +| Server-side encryption at rest | ✅ Always on | Applied automatically by the regional storage gateway — no headers required, and it cannot be disabled. | +| Encryption in transit (TLS) | ✅ Always on | All API connections use HTTPS. HTTP is rejected. | +| `GetBucketEncryption` / `PutBucketEncryption` | ❌ Not available to access keys | No access key can be granted these actions, in either region. Encryption is on either way and cannot be modified or disabled. | +| SSE-S3 (`AES256`) header | Not needed | Encryption is applied automatically in both regions, so send no encryption header. | +| SSE-KMS (`aws:kms`) | ❌ Not supported | Rejected in **both** regions: `InvalidRequest` in `us-east-1`, and `AccessDenied` or `InvalidRequest` in `eu-west-1` depending on the operation. Affects `PutObject`, `CopyObject`, and `CreateMultipartUpload`. Omit encryption headers, server-side encryption is applied automatically. | +| SSE-C (customer-provided keys) | ❌ Not supported | Keys are held by the regional storage operator. There is no customer-managed-key option. Requests carrying SSE-C headers are rejected in `eu-west-1`; not yet confirmed in `us-east-1`. Don't send them. | +| Client-side encryption | ✅ Optional | Encrypt data in your own application before upload. AWS's S3 Encryption Client exists only for some SDKs (Java, .NET, Go, Ruby) — not boto3, the CLI, or JS v3 — so with those you supply your own crypto. Server-side encryption is still applied on top. | + +See [Encryption](https://docs.filone.com/security/encryption) for details. + +## ACLs + +The S3 ACL model is **not supported**. Fil One does not implement bucket or object ACLs, bucket policies, or public access controls. All access requires SigV4 authentication. + +How an ACL request fails depends on **how** you send it. Confirmed in `eu-west-1`: + +| What you send | Behavior | +|---------------|----------| +| A canned-ACL header on an upload (`--acl public-read` in the AWS CLI, `ACL: 'public-read'` on a `PutObject` SDK call) | The flag is silently ignored. The upload **succeeds** and the object is stored, but no ACL is applied and the object does not become public. | +| A dedicated ACL call (`PutBucketAcl`, `PutObjectAcl`, `GetBucketAcl`, `GetObjectAcl`) | Rejected with `AccessDenied` (403). | + +So a tool that uploads with `--acl public-read` will appear to work, while a tool that sets ACLs as a separate step will fail outright. In neither case does the object become publicly readable. If you need unauthenticated access to an object, use a [presigned URL](#presigned-urls). + +To limit what a key can reach, scope it to specific buckets when you create it. See [Bucket scope](https://docs.filone.com/security/api-keys#bucket-scope). + +## Not yet supported + +| Feature | Timeline | Notes | +|---------|----------|-------| +| Lifecycle rules (expiration, transitions) | Planned | Affects archival and cleanup workflows. | +| Event notifications (SNS/SQS/Lambda triggers) | Planned | | +| Object and bucket tagging | Planned | | +| Additional regions | Planned | `eu-west-1` and `us-east-1` are available today. | +| IAM users, roles, and bucket policies on the S3 API | Not yet supported | The S3 API has no IAM users, roles, or bucket policies. Access is controlled by each access key's permissions and bucket scope. Team members and roles exist in the console: see [Organization](https://docs.filone.com/app/organization#roles-and-permissions). | +| S3 Select | Not planned | | +| S3 Inventory | Not planned | | +| S3 Batch Operations | Not planned | | +| Multiple storage classes | Not planned | Single storage class. | + +## Error responses + +Fil One returns standard S3 error XML, in the shape below, for all error conditions. + +```xml + + + NoSuchBucket + The specified bucket does not exist. + my-bucket + abc123 + +``` + +The **format** is standard, but the specific code returned for a given condition does not always match AWS. If your application only surfaces error messages, no changes are needed. If it *branches* on error codes or HTTP statuses, review the deviations below. + +See the [Error Reference](https://docs.filone.com/reference/errors) for a full list of error codes. + +### Known error-code deviations in `eu-west-1` + +Confirmed by a compatibility test run against the region. + +| Condition | AWS S3 returns | Fil One `eu-west-1` returns | +|-----------|----------------|------------------------------| +| Any unimplemented operation | `NotImplemented` (501) | `AccessDenied` (403) | +| Reading a bucket or key you cannot see | `NoSuchBucket` / `NoSuchKey` (404) | `AccessDenied` (403) | +| A checksum that does not match the body | `BadDigest` | `InvalidArgument` | +| An unsatisfiable `Range` header | `InvalidRange` | `InvalidArgument` | +| An invalid object tag | `InvalidTag` | `BadRequest` | +| `CreateBucket` on a bucket you already own | `BucketAlreadyExists` in most regions | `BucketAlreadyOwnedByYou` | +| A malformed `PutPublicAccessBlock` or `PutBucketLogging` body | `MalformedXML` for genuinely bad XML only | `MalformedXML` even for a well-formed body, since neither operation is implemented | -### Presigned URLs +Some invalid requests are also **accepted** where AWS rejects them (HTTP 200 or 204 instead of 400). Do not rely on the gateway to validate request parameters for you: validate on the client side where correctness matters. -Presigned GetObject and PutObject are both supported. +## Known behavioral issues in `eu-west-1` -### Server-side encryption +These are confirmed deviations that can affect a correctly written S3 client. They are known issues, not intended behavior. -Always on for every bucket, nothing to configure, cannot be disabled. Keys -are held by the regional storage operator, not by Fil One and not -customer-managed. No SSE-C: requests carrying SSE-C headers are rejected in -eu-west-1. No SSE-KMS either, and it is now confirmed REJECTED IN BOTH REGIONS: -InvalidRequest in us-east-1, AccessDenied or InvalidRequest in eu-west-1 -depending on the operation (PutObject, CopyObject, CreateMultipartUpload). Omit -encryption headers entirely, encryption is applied regardless. SSE-S3 (AES256) is -accepted in us-east-1, but in eu-west-1 the bucket-level SSE-S3 configuration -operations are rejected with AccessDenied. Encryption in transit (TLS) is always -on; HTTP is rejected. - -### ACLs - -The S3 ACL model is NOT implemented: no bucket or object ACLs, no bucket -policies, no public access controls. All access requires SigV4 auth. HOW an ACL -request fails depends on how it is sent (confirmed in eu-west-1): - -- A canned-ACL HEADER on an upload (--acl public-read, ACL: 'public-read' on - PutObject) is SILENTLY IGNORED. The upload SUCCEEDS, no ACL is applied, and the - object does NOT become public. -- A DEDICATED ACL CALL (PutBucketAcl, PutObjectAcl, GetBucketAcl, GetObjectAcl) - is REJECTED with AccessDenied (403). - -So a tool that uploads with --acl public-read appears to work while a tool that -sets ACLs as a separate step fails outright. Neither makes an object public. Use a -presigned URL for unauthenticated access. To limit what a key can reach, scope it -to specific buckets when you create it (see API Keys, Bucket scope). - -### Known error-code deviations in eu-west-1 - -The error XML FORMAT is standard, but the CODE for a given condition often is not. -Applications that branch on error codes need review; ones that only surface -messages do not. - -| Condition | AWS S3 | Fil One eu-west-1 | -|-----------|--------|-------------------| -| Any unimplemented operation | NotImplemented (501) | AccessDenied (403) | -| Bucket or key you cannot see | NoSuchBucket / NoSuchKey (404) | AccessDenied (403) | -| Checksum not matching the body | BadDigest | InvalidArgument | -| Unsatisfiable Range header | InvalidRange | InvalidArgument | -| Invalid object tag | InvalidTag | BadRequest | -| CreateBucket on a bucket you own | BucketAlreadyExists (most regions) | BucketAlreadyOwnedByYou | -| Malformed PutPublicAccessBlock / PutBucketLogging body | MalformedXML for bad XML only | MalformedXML even for a well-formed body (neither is implemented) | - -Some invalid requests are also ACCEPTED where AWS rejects them (200/204 instead of -400). Do not rely on the gateway to validate request parameters; validate -client-side where correctness matters. - -### Known behavioral issues in eu-west-1 - -Confirmed deviations that can break a correctly written S3 client. Open -engineering issues, NOT intended behavior. - -- PAGINATION: ListObjects may return a NextMarker with an internal suffix - appended to the key (e.g. "asdf[...]" instead of "asdf"). Feeding it back as the - next Marker does not resume correctly. Prefer ListObjectsV2 with - ContinuationToken, which is unaffected; otherwise page using the last returned - key rather than trusting NextMarker. -- URL ENCODING: with EncodingType=url, a space in a key or prefix is encoded as - "+" instead of "%20". Most SDKs decode only %20, so keys with spaces come back - wrong. Avoid spaces in keys, or decode "+" as a space yourself. -- CHECKSUMS: additional-checksum operations are unreliable. - CompleteMultipartUpload may omit ChecksumType from its response, and mismatches - surface as InvalidArgument rather than BadDigest. Verify with ETags or your own - post-download hash. - -### Not yet supported - -Bucket/object ACLs, bucket policies, lifecycle rules (expiration, -transitions), event notifications, object and bucket tagging, S3 Select, S3 -Inventory, S3 Batch Operations, multiple storage classes, additional regions -beyond eu-west-1 and us-east-1. IAM users, roles, and bucket policies on the S3 -API are NOT YET SUPPORTED: access is controlled by each access key's permissions -and bucket scope. Team members and roles exist in the console, in beta (see App: -Organization). +| Area | Issue | Workaround | +|------|-------|------------| +| Pagination | `ListObjects` may return a `NextMarker` with an internal suffix appended to the key (for example `asdf[...]` instead of `asdf`). Feeding that value back as the next `Marker` will not resume where you left off. | Prefer `ListObjectsV2` with `ContinuationToken`, which is unaffected. If you must use `ListObjects`, do not trust `NextMarker`; page using the last returned key instead. | +| URL encoding | With `EncodingType=url`, a space in a key or prefix is encoded as `+` rather than `%20`. Most SDKs decode `%20` only, so keys with spaces can come back wrong. | Avoid spaces in key names, or decode `+` as a space yourself when you request URL encoding. | +| Checksums | Additional-checksum operations are unreliable. `CompleteMultipartUpload` may omit `ChecksumType` from its response, and checksum mismatches surface as `InvalidArgument` rather than `BadDigest`. | Verify integrity with ETags, or compare a hash you compute yourself after download. | ## Differences from AWS S3 +Fil One is S3-compatible, not an S3 clone. A few behaviors differ: + | Behavior | AWS S3 | Fil One | |----------|--------|---------| -| Versioning | Configurable — enable, suspend, or leave off per bucket. | Opt-in at bucket creation. Once enabled, cannot be suspended or disabled. No restore/roll-back from the dashboard; achievable via the API in us-east-1 using CopyObject. | -| Server-side copy | CopyObject supported. | Confirmed working in us-east-1. In eu-west-1 plain copy works, but the version-id form (promoting an old version) is unverified. | -| Encryption | Optional and configurable. Off by default for older buckets. | Always on. Cannot be disabled. Keys held by the regional storage operator; no customer-managed keys. | -| Bucket management | CreateBucket and DeleteBucket via API. Requires an empty bucket to delete. | Region-dependent. Supported via API in us-east-1; in eu-west-1 buckets are managed through the dashboard only. | -| IAM and policies | Full IAM with users, roles, and bucket policies. | No IAM users, roles, or bucket policies on the S3 API. Access is controlled by each access key's permissions and bucket scope. The console has organizations with member roles, in beta (see App: Organization). | -| Public access | Configurable via ACLs and bucket policies. | No public access. All requests require authentication. Canned-ACL headers on uploads are ignored rather than rejected and never make an object public. | -| Error codes for missing features | NotImplemented (501). | AccessDenied (403) in eu-west-1. A 403 on a bucket-configuration call means the feature is absent, not that the key lacks permission. | +| Versioning | Configurable — can be enabled, suspended, or left off per bucket. | Opt-in at bucket creation. Once enabled, cannot be suspended or disabled. No restore/roll-back from the dashboard; achievable via the API in `us-east-1` using `CopyObject`. | +| Server-side copy | `CopyObject` supported. | Confirmed working in `us-east-1`. In `eu-west-1` plain copy works, but the version-id form (promoting an old version) is unverified. | +| Encryption | Optional and configurable. Off by default for older buckets. | Always on. Cannot be disabled. Keys are held by the regional storage operator; no customer-managed keys. | +| Bucket management | `CreateBucket` and `DeleteBucket` supported via API. Requires an empty bucket to delete. | Region-dependent. Supported via API in `us-east-1`; in `eu-west-1` buckets are managed through the dashboard only. | +| IAM and policies | Full IAM with users, roles, and bucket policies. | No IAM users, roles, or bucket policies on the S3 API. Access is controlled by each access key's permissions and bucket scope. The console has organizations with member roles: see [Organization](https://docs.filone.com/app/organization#roles-and-permissions). | +| Public access | Configurable via ACLs and bucket policies. | No public access. All requests require authentication. Canned-ACL headers on uploads are ignored rather than rejected, and never make an object public. | +| Error codes for missing features | `NotImplemented` (501). | `AccessDenied` (403) in `eu-west-1`. A 403 on a bucket-configuration call means the feature is absent, not that your key lacks permission. | | Lifecycle rules | Supported (expiration, storage class transitions). | Not supported. Planned for a future release. | | Object Lock modes | Compliance and Governance. | Compliance and Governance, in both regions, with Legal Hold. | | Storage classes | Multiple (Standard, IA, Glacier, etc.). | Single storage class. | -| Regions | 30+ globally. | Two: eu-west-1 and us-east-1. Additional regions planned. | +| Regions | 30+ globally. | Two: `eu-west-1` and `us-east-1`. Additional regions planned. | | Data retention after deletion | Object is immediately and permanently deleted. | Object is immediately inaccessible in Fil One, but the underlying Filecoin storage may persist for a bounded period until the sealed sector naturally expires. That residual data stays encrypted. | @@ -2589,10 +2802,7 @@ Organization). Source: https://docs.filone.com/reference/errors -Fil One returns standard S3 error responses in XML format. The FORMAT is standard; -the CODE for a given condition does not always match AWS, so an application that -branches on error codes needs review. See "Known error-code deviations in -eu-west-1" under S3 Compatibility. +Fil One returns standard S3 error responses in XML format. The format is standard, but the specific code returned for a given condition does not always match AWS S3, so an application that branches on error codes needs review. See [known error-code deviations](https://docs.filone.com/reference/s3-compatibility#known-error-code-deviations-in-eu-west-1). ## Error response format @@ -2608,50 +2818,62 @@ eu-west-1" under S3 Compatibility. ## Common error codes +Note: +Fil One returns standard S3-style error XML. The specific codes and HTTP statuses below are the common AWS S3 values, provided as a guide — the authoritative set is produced by the storage gateway and has not been exhaustively verified against Fil One. Handle unlisted codes defensively. + ### Client errors (4xx) -| Code | HTTP | Description | -|------|------|-------------| -| AccessDenied | 403 | No permission OR the operation is not implemented. In eu-west-1 unimplemented operations return this instead of NotImplemented (501), and a hidden bucket/key returns it instead of a 404. Check the compatibility matrix before assuming a key-scope problem. | -| BucketAlreadyExists | 409 | Bucket name already taken. If you already own the bucket, eu-west-1 returns BucketAlreadyOwnedByYou. | -| InvalidAccessKeyId | 403 | Key does not exist or has been revoked. | -| InvalidBucketName | 400 | Name does not meet naming requirements. | -| NoSuchBucket | 404 | Bucket does not exist. | -| NoSuchKey | 404 | Object does not exist. | -| SignatureDoesNotMatch | 403 | Request signature mismatch. Check secret key and signing method. | -| TooManyBuckets | 400 | Account bucket limit reached. | +| Code | HTTP Status | Description | +|------|-------------|-------------| +| `AccessDenied` | 403 | You do not have permission **or** the operation is not implemented. In `eu-west-1`, unimplemented operations return this instead of `NotImplemented` (501), and a hidden bucket or key returns it instead of a 404. Check the [compatibility matrix](https://docs.filone.com/reference/s3-compatibility) before assuming a key-scope problem. | +| `BucketAlreadyExists` | 409 | The bucket name is already taken. If the bucket is one you already own, `eu-west-1` returns `BucketAlreadyOwnedByYou` instead. | +| `BucketNotEmpty` | 409 | The bucket is not empty and cannot be deleted. | +| `InvalidAccessKeyId` | 403 | The access key does not exist or has been revoked. | +| `InvalidBucketName` | 400 | The bucket name does not meet naming requirements. | +| `InvalidArgument` | 400 | A request parameter is invalid. | +| `NoSuchBucket` | 404 | The specified bucket does not exist. | +| `NoSuchKey` | 404 | The specified object does not exist. | +| `SignatureDoesNotMatch` | 403 | The request signature does not match. Check your secret key and signing method. | +| `TooManyBuckets` | 400 | You have reached the maximum number of buckets. | ### Server errors (5xx) -| Code | HTTP | Description | -|------|------|-------------| -| InternalError | 500 | Retry the request. | -| ServiceUnavailable | 503 | Temporarily unavailable. Check Retry-After header. | -| SlowDown | 503 | Too many requests. Implement exponential backoff. | +| Code | HTTP Status | Description | +|------|-------------|-------------| +| `InternalError` | 500 | An internal error occurred. Retry the request. | +| `ServiceUnavailable` | 503 | The service is temporarily unavailable. Check the `Retry-After` header. | +| `SlowDown` | 503 | You are sending requests too quickly. Implement exponential backoff. | ## Console errors -These come from the Fil One console at app.filone.com, NOT from the S3 API. +These come from the Fil One console at [app.filone.com](https://app.filone.com), not from the S3 API. -| Message | HTTP | What to do | -|---------|------|------------| -| "We are still setting up your account. Please try again in a moment." | 503 | Shown while a new account is being set up. Wait and retry. | -| "We are still setting up the region for you. Please try again in a moment." | 503 | Shown while a region is being set up for your account. Wait and retry. | -| A message that your role does not permit the action | 403 | Your organization role doesn't include this action. Ask an Owner or Admin. | +| Message | HTTP Status | What to do | +|---------|-------------|------------| +| "We are still setting up your account. Please try again in a moment." | 503 | Shown while a new account is being set up. Wait a moment and retry. | +| "We are still setting up the region for you. Please try again in a moment." | 503 | Shown while a region is being set up for your account. Wait a moment and retry. | +| A message that your role does not permit the action | 403 | Your [role](https://docs.filone.com/app/organization#roles-and-permissions) doesn't include this action. Ask an Owner or Admin. | ## Troubleshooting -**SignatureDoesNotMatch**: Re-copy your secret key from the dashboard. Ensure your -system clock is accurate (SigV4 requires clocks within 15 minutes of server time). -Verify the region matches your key and endpoint (eu-west-1 or us-east-1); a key is -scoped to one region and is rejected against the other. +**`SignatureDoesNotMatch`** -- The most common auth error. Check that: +1. Your secret key is correct (re-copy from the dashboard if unsure). +2. Your system clock is accurate (SigV4 requires clocks within 15 minutes of server time). +3. You are using the region that matches your key and endpoint (`eu-west-1` or `us-east-1`). A key is scoped to one region and is rejected against the other. -**AccessDenied (403)**: NOT always a permissions problem. In eu-west-1 this is also -what an unimplemented operation returns, and what you get instead of a 404 for a -bucket or key you cannot see. Confirm the operation is supported in your region -before auditing access-key scopes. +**`AccessDenied` (403)** -- Not always a permissions problem. In `eu-west-1` this is also what an unimplemented operation returns, and what you get instead of a 404 for a bucket or key you cannot see. Confirm the operation is supported in your region in the [compatibility matrix](https://docs.filone.com/reference/s3-compatibility) before auditing your access-key scopes. -**ServiceUnavailable (503)**: Transient. Retry with exponential backoff. If persistent, check https://status.filone.com. +**`ServiceUnavailable` (503)** -- Transient. Retry with exponential backoff. If persistent, check [status.filone.com](https://status.filone.com). + +### First-request problems + +| Symptom | Likely cause | Fix | +|---------|--------------|-----| +| `InvalidAccessKeyId`, `SignatureDoesNotMatch` or 403 on every request, with a key you just created | The key, the endpoint and the region setting don't all refer to the same region | Use the endpoint and region of the key's region. A key created for `us-east-1` is rejected by `s3.eu-west-1.filonecontent.com`, and the other way round. | +| DNS lookup failure or a connection error for a host like `my-bucket.s3.eu-west-1.filonecontent.com` | The client is using virtual-hosted-style addressing | Enable path-style addressing in your client. See [SDKs & Tools](https://docs.filone.com/sdk/overview#connection-details). | +| `AccessDenied` when deleting an object, although uploads work | The key doesn't have the **Delete** permission. It isn't pre-selected when you create a key | Create a key with **Delete**, or rotate this one with it added. See [API Keys](https://docs.filone.com/security/api-keys#key-permissions). | +| `BadDigest` when a browser uploads to a presigned URL made with the AWS SDK for JavaScript | SDK v3.729 and later sign a checksum computed when the URL is made, which the real upload doesn't match | Set `requestChecksumCalculation: "WHEN_REQUIRED"` on the `S3Client` that creates the URL. See [JavaScript](https://docs.filone.com/sdk/javascript#presigned-urls). | +| `list-multipart-uploads` or `abort-multipart-upload` fails with 403 in `us-east-1` | Keys created there before 26 August 2026 don't carry these multipart actions, and existing keys can't be updated | Create a new key. See [Cleaning up incomplete uploads](https://docs.filone.com/storage/multipart-uploads#cleaning-up-incomplete-uploads). | --- @@ -2660,37 +2882,56 @@ before auditing access-key scopes. Source: https://docs.filone.com/sdk/overview -Fil One works with any tool or library that supports the S3 API. +Fil One works with any tool or library that supports the S3 API. You do not need a custom SDK -- configure your existing S3 tools to point at your region's endpoint and authenticate with your API keys. + +## Recommended tools + +| Tool | Language / Platform | Install | +|------|-------------------|---------| +| AWS CLI (v2) | Command line | `brew install awscli` (v2.13 or later, which reads `endpoint_url` from a profile) | +| boto3 | Python | `pip install boto3` | +| AWS SDK v3 | JavaScript / TypeScript | `npm install @aws-sdk/client-s3` | +| aws-sdk-go-v2 | Go | `go get github.com/aws/aws-sdk-go-v2/service/s3` | +| rclone | Command line (multi-platform) | [rclone.org/install](https://rclone.org/install/) | +| Cyberduck | macOS / Windows GUI | [cyberduck.io](https://cyberduck.io) | ## Connection details +Every SDK and tool needs the same four things: + | Parameter | Value | |-----------|-------| -| Endpoint | https://s3.eu-west-1.filonecontent.com | -| Region | eu-west-1 | -| Credentials | Access Key ID + Secret Access Key from dashboard | +| Endpoint | `https://s3..filonecontent.com` | +| Region | `eu-west-1` or `us-east-1` | +| Credentials | Your Access Key ID and Secret Access Key, from **API Keys** in the console | +| Path-style addressing | **Required.** Fil One does not support virtual-hosted-style URLs — enable path-style in every client (`forcePathStyle`, `addressing_style = path`, `UsePathStyle`, etc.) | -## Recommended tools +The endpoint is region-specific, and it has to match the region of the bucket you are addressing: + +| Region | Endpoint | +|--------|----------| +| Europe (France) `eu-west-1` (default) | `https://s3.eu-west-1.filonecontent.com` | +| US East (Michigan) `us-east-1` | `https://s3.us-east-1.filonecontent.com` | -| Tool | Platform | Install | -|------|----------|---------| -| AWS CLI | Command line | pip install awscli | -| boto3 | Python | pip install boto3 | -| AWS SDK v3 | JavaScript/TypeScript | npm install @aws-sdk/client-s3 | -| aws-sdk-go-v2 | Go | go get github.com/aws/aws-sdk-go-v2/service/s3 | -| rclone | Multi-platform CLI | rclone.org/install | -| Cyberduck | macOS/Windows GUI | cyberduck.io | +Access keys are also scoped to a single region, so a key issued for `eu-west-1` will not work against `us-east-1`. Code examples throughout these docs use `eu-west-1` because it is the default — substitute your own region where it differs. + +## Quick setup guides + +- [Python (boto3)](https://docs.filone.com/sdk/python): Full examples for upload, download, and multipart. +- [JavaScript](https://docs.filone.com/sdk/javascript): AWS SDK v3 examples for Node.js and browser. +- [Go](https://docs.filone.com/sdk/go): aws-sdk-go-v2 examples for server-side applications. +- [AWS CLI](https://docs.filone.com/sdk/cli): Command-line reference for common operations. ## Third-party tools -Most S3-compatible tools work, subject to the same constraints as any S3 client -(path-style required, plus the documented compatibility gaps). These have -specific setup notes: +Most S3-compatible tools work with Fil One, subject to the same constraints as any S3 client — path-style addressing is required, and the gaps in the [S3 Compatibility Reference](https://docs.filone.com/reference/s3-compatibility) apply. These have specific setup notes: -- **rclone**: Sync files with `rclone config` using S3 provider type. -- **Cyberduck**: Add S3 connection with the Fil One endpoint. -- **s3cmd**: Configure with `s3cmd --configure`, set host to s3.eu-west-1.filonecontent.com. -- **MinIO Client**: `mc alias set filone https://s3.eu-west-1.filonecontent.com YOUR_KEY YOUR_SECRET` +- **rclone** -- Sync files between local storage and Fil One. Configure with `rclone config` using the S3 provider type. +- **Cyberduck** -- GUI file browser for macOS and Windows. Add a new S3 connection with the Fil One endpoint. +- **s3cmd** -- Command-line tool. Configure with `s3cmd --configure`, then set both `host_base = s3.eu-west-1.filonecontent.com` and `host_bucket = s3.eu-west-1.filonecontent.com/%(bucket)s` in `~/.s3cfg`. The `host_bucket` line is what forces path-style addressing; without it s3cmd stays in virtual-hosted mode and requests fail. +- **MinIO Client (mc)** -- `mc alias set filone https://s3.eu-west-1.filonecontent.com YOUR_ACCESS_KEY YOUR_SECRET_KEY`. Passing the secret on the command line leaves it in your shell history and the process list — prefer `mc alias set filone https://s3.eu-west-1.filonecontent.com` and let `mc` prompt for the key and secret interactively. + +If you use a tool not listed here and run into compatibility issues, [contact support](https://docs.filone.com/app/support). --- @@ -2699,6 +2940,13 @@ specific setup notes: Source: https://docs.filone.com/sdk/python +Fil One works with [boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html), the AWS SDK for Python — it is S3-API compatible, so no custom library is needed. Configure the client to point at the Fil One endpoint, **enable path-style addressing**, and use the standard API. A few S3 operations are not supported; see [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility) for the exceptions. + +Note: The endpoint depends on your bucket's region +Examples here use `eu-west-1`, the default region. For a bucket in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and `region_name="us-east-1"`. The endpoint, the region, and your access key must all refer to the same region. + +## Installation + ```bash pip install boto3 ``` @@ -2707,40 +2955,81 @@ pip install boto3 ```python import boto3 -import os +from botocore.config import Config s3 = boto3.client( "s3", endpoint_url="https://s3.eu-west-1.filonecontent.com", - aws_access_key_id=os.environ["FIL_ACCESS_KEY"], - aws_secret_access_key=os.environ["FIL_SECRET_KEY"], region_name="eu-west-1", + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), ) ``` +boto3 reads your key from the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables, the names the console's **Download .env** writes. Never hardcode credentials in source code. + +`signature_version="s3v4"` makes presigned URLs use SigV4. Without it, boto3 can sign presigned URLs with the older SigV2 scheme when you set a custom endpoint. + +Warning: Path-style addressing is required +Fil One only supports **path-style** URLs (`https://s3.eu-west-1.filonecontent.com/my-bucket/key`). boto3 defaults to virtual-hosted style (`https://my-bucket.s3.eu-west-1.filonecontent.com/key`) even with a custom `endpoint_url`, which fails with a DNS or 404-shaped error. Keep the `s3={"addressing_style": "path"}` setting above. `region_name` is also required, since SigV4 cannot sign without a region. + ## Core operations +### Create a bucket + +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a `us-east-1` client and a `us-east-1` key that has the `CreateBucket` permission: + +```python +s3_us = boto3.client( + "s3", + endpoint_url="https://s3.us-east-1.filonecontent.com", + region_name="us-east-1", + config=Config(signature_version="s3v4", s3={"addressing_style": "path"}), +) +s3_us.create_bucket(Bucket="my-bucket") +``` + +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](https://docs.filone.com/storage/buckets). + +### Upload an object + ```python -# Upload +# Upload from a local file path (report.pdf must exist) s3.upload_file("report.pdf", "my-bucket", "reports/report.pdf") -s3.put_object(Bucket="my-bucket", Key="data/file.json", - Body=b'{"key": "value"}', ContentType="application/json") -# Download +# Upload with content type +s3.put_object( + Bucket="my-bucket", + Key="data/file.json", + Body=b'{"key": "value"}', + ContentType="application/json", +) +``` + +### Download an object + +```python s3.download_file("my-bucket", "reports/report.pdf", "local-report.pdf") +``` + +### List objects -# List (with pagination) +```python paginator = s3.get_paginator("list_objects_v2") for page in paginator.paginate(Bucket="my-bucket"): for obj in page.get("Contents", []): print(obj["Key"], obj["Size"]) +``` -# Delete +### Delete an object + +```python s3.delete_object(Bucket="my-bucket", Key="reports/report.pdf") ``` ## Multipart uploads +boto3's `upload_file` and `upload_fileobj` switch to multipart automatically for any file larger than the `multipart_threshold`, which defaults to **8 MB** (not 5 GB). You can configure the threshold and concurrency: + ```python from boto3.s3.transfer import TransferConfig @@ -2749,18 +3038,21 @@ config = TransferConfig( multipart_chunksize=50 * 1024 * 1024, # 50 MB max_concurrency=10, ) + s3.upload_file("large-file.zip", "my-bucket", "large-file.zip", Config=config) ``` ## Presigned URLs ```python +# Download URL valid for 1 hour download_url = s3.generate_presigned_url( "get_object", Params={"Bucket": "my-bucket", "Key": "reports/report.pdf"}, ExpiresIn=3600, ) +# Upload URL valid for 15 minutes upload_url = s3.generate_presigned_url( "put_object", Params={"Bucket": "my-bucket", "Key": "uploads/new-file.txt"}, @@ -2785,6 +3077,8 @@ except ClientError as e: raise ``` +See the [Error Reference](https://docs.filone.com/reference/errors) for a full list of error codes. + --- @@ -2792,6 +3086,13 @@ except ClientError as e: Source: https://docs.filone.com/sdk/javascript +Fil One works with the [AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/) — it is S3-API compatible. Point the client at the Fil One endpoint with `forcePathStyle: true` and use the standard API. A few S3 operations are not supported; see [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility) for the exceptions. + +Note: The endpoint depends on your bucket's region +Examples here use `eu-west-1`, the default region. For a bucket in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and `region: "us-east-1"`. The endpoint, the region, and your access key must all refer to the same region. + +## Installation + ```bash npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner ``` @@ -2804,64 +3105,128 @@ import { S3Client } from "@aws-sdk/client-s3"; const s3 = new S3Client({ endpoint: "https://s3.eu-west-1.filonecontent.com", region: "eu-west-1", - forcePathStyle: true, // required - credentials: { - accessKeyId: process.env.FIL_ACCESS_KEY, - secretAccessKey: process.env.FIL_SECRET_KEY, - }, + forcePathStyle: true, + // SDK v3.729+ adds checksums Fil One doesn't accept on presigned uploads + requestChecksumCalculation: "WHEN_REQUIRED", + responseChecksumValidation: "WHEN_REQUIRED", }); ``` +The SDK reads your key from the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables, the names the console's **Download .env** writes. Never hardcode credentials in source code. + +The examples use ES modules and top-level `await`: save them as `.mjs` files, or run `npm pkg set type=module` in your project. + +Warning: Set the checksum options +Since v3.729, the SDK adds a CRC32 checksum to requests by default. On a presigned upload URL, that checksum is computed when the URL is made, so the real upload doesn't match it and Fil One rejects it with `BadDigest`. `requestChecksumCalculation: "WHEN_REQUIRED"` restores the earlier behavior. Fil One's own console sets the same options. + ## Core operations +### Create a bucket + +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a `us-east-1` client and a `us-east-1` key that has the `CreateBucket` permission: + +```javascript +import { S3Client, CreateBucketCommand } from "@aws-sdk/client-s3"; + +const s3Us = new S3Client({ + endpoint: "https://s3.us-east-1.filonecontent.com", + region: "us-east-1", + forcePathStyle: true, +}); + +await s3Us.send(new CreateBucketCommand({ Bucket: "my-bucket" })); +``` + +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](https://docs.filone.com/storage/buckets). + +### Upload an object + ```javascript -import { - PutObjectCommand, GetObjectCommand, ListObjectsV2Command, - DeleteObjectCommand -} from "@aws-sdk/client-s3"; -import { readFileSync, writeFileSync } from "fs"; +import { PutObjectCommand } from "@aws-sdk/client-s3"; +import { readFileSync } from "fs"; -// Upload +// Upload a buffer await s3.send(new PutObjectCommand({ - Bucket: "my-bucket", Key: "data/file.json", + Bucket: "my-bucket", + Key: "data/file.json", Body: JSON.stringify({ key: "value" }), ContentType: "application/json", })); -// Download (streaming) +// Upload a local file (report.pdf must exist) +await s3.send(new PutObjectCommand({ + Bucket: "my-bucket", + Key: "reports/report.pdf", + Body: readFileSync("report.pdf"), + ContentType: "application/pdf", +})); +``` + +### Download an object + +```javascript +import { GetObjectCommand } from "@aws-sdk/client-s3"; +import { writeFileSync } from "fs"; + const response = await s3.send(new GetObjectCommand({ - Bucket: "my-bucket", Key: "reports/report.pdf", + Bucket: "my-bucket", + Key: "reports/report.pdf", })); + +// Convert stream to buffer const chunks = []; -for await (const chunk of response.Body) chunks.push(chunk); +for await (const chunk of response.Body) { + chunks.push(chunk); +} writeFileSync("local-report.pdf", Buffer.concat(chunks)); +``` + +### List objects + +```javascript +import { ListObjectsV2Command } from "@aws-sdk/client-s3"; -// List (with pagination) let continuationToken; do { const response = await s3.send(new ListObjectsV2Command({ - Bucket: "my-bucket", ContinuationToken: continuationToken, + Bucket: "my-bucket", + ContinuationToken: continuationToken, })); - for (const obj of response.Contents ?? []) console.log(obj.Key, obj.Size); + for (const obj of response.Contents ?? []) { + console.log(obj.Key, obj.Size); + } continuationToken = response.NextContinuationToken; } while (continuationToken); +``` + +### Delete an object + +```javascript +import { DeleteObjectCommand } from "@aws-sdk/client-s3"; -// Delete -await s3.send(new DeleteObjectCommand({ Bucket: "my-bucket", Key: "file.txt" })); +await s3.send(new DeleteObjectCommand({ + Bucket: "my-bucket", + Key: "reports/report.pdf", +})); ``` ## Presigned URLs ```javascript import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; +import { GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3"; +// Download URL valid for 1 hour const downloadUrl = await getSignedUrl( - s3, new GetObjectCommand({ Bucket: "my-bucket", Key: "reports/report.pdf" }), + s3, + new GetObjectCommand({ Bucket: "my-bucket", Key: "reports/report.pdf" }), { expiresIn: 3600 } ); +// Upload URL valid for 15 minutes const uploadUrl = await getSignedUrl( - s3, new PutObjectCommand({ Bucket: "my-bucket", Key: "uploads/new-file.txt" }), + s3, + new PutObjectCommand({ Bucket: "my-bucket", Key: "uploads/new-file.txt" }), { expiresIn: 900 } ); ``` @@ -2869,7 +3234,7 @@ const uploadUrl = await getSignedUrl( ## Error handling ```javascript -import { S3ServiceException } from "@aws-sdk/client-s3"; +import { GetObjectCommand, S3ServiceException } from "@aws-sdk/client-s3"; try { await s3.send(new GetObjectCommand({ Bucket: "my-bucket", Key: "missing.txt" })); @@ -2882,6 +3247,8 @@ try { } ``` +See the [Error Reference](https://docs.filone.com/reference/errors) for a full list of error codes. + --- @@ -2889,7 +3256,17 @@ try { Source: https://docs.filone.com/sdk/go +Fil One works with [aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) — it is S3-API compatible. Configure the client to point at the Fil One endpoint with `UsePathStyle: true` and use the standard S3 API. A few S3 operations are not supported; see [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility) for the exceptions. + +Note: The endpoint depends on your bucket's region +Examples here use `eu-west-1`, the default region. For a bucket in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and `Region: "us-east-1"`. The endpoint, the region, and your access key must all refer to the same region. + +## Installation + +In a new directory, create a module and add the SDK: + ```bash +go mod init example.com/filone go get github.com/aws/aws-sdk-go-v2/aws go get github.com/aws/aws-sdk-go-v2/credentials go get github.com/aws/aws-sdk-go-v2/service/s3 @@ -2898,77 +3275,206 @@ go get github.com/aws/aws-sdk-go-v2/service/s3 ## Client configuration ```go +package main + +import ( + "os" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/s3" +) + func newClient() *s3.Client { return s3.New(s3.Options{ BaseEndpoint: aws.String("https://s3.eu-west-1.filonecontent.com"), Region: "eu-west-1", - UsePathStyle: true, // required Credentials: credentials.NewStaticCredentialsProvider( - os.Getenv("FIL_ACCESS_KEY"), - os.Getenv("FIL_SECRET_KEY"), + os.Getenv("AWS_ACCESS_KEY_ID"), + os.Getenv("AWS_SECRET_ACCESS_KEY"), "", ), + UsePathStyle: true, }) } ``` +Set `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` as environment variables, the names the console's **Download .env** writes. Never hardcode credentials in source code. + +The operation snippets below are fragments: each assumes the `client` returned by `newClient()` above, a `ctx` (e.g. `ctx := context.TODO()`), and `"log"` imported, and shows only the other imports specific to that snippet. + ## Core operations +### Create a bucket + +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a client built with the `us-east-1` endpoint and region, and a `us-east-1` key that has the `CreateBucket` permission: + +```go +// usClient: like newClient(), with BaseEndpoint https://s3.us-east-1.filonecontent.com and Region "us-east-1" +_, err := usClient.CreateBucket(ctx, &s3.CreateBucketInput{ + Bucket: aws.String("my-bucket"), +}) +if err != nil { + log.Fatal(err) +} +``` + +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](https://docs.filone.com/storage/buckets). + +### Upload an object + ```go +import ( + "bytes" + "os" +) + // Upload bytes -client.PutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String("my-bucket"), Key: aws.String("data/file.json"), - Body: bytes.NewReader([]byte(`{"key":"value"}`)), +_, err := client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String("my-bucket"), + Key: aws.String("data/file.json"), + Body: bytes.NewReader([]byte(`{"key":"value"}`)), ContentType: aws.String("application/json"), }) +if err != nil { + log.Fatal(err) +} -// Upload file -f, _ := os.Open("report.pdf") +// Upload a local file (report.pdf must exist) +f, err := os.Open("report.pdf") +if err != nil { + log.Fatal(err) +} defer f.Close() -client.PutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String("my-bucket"), Key: aws.String("reports/report.pdf"), - Body: f, ContentType: aws.String("application/pdf"), + +_, err = client.PutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String("my-bucket"), + Key: aws.String("reports/report.pdf"), + Body: f, + ContentType: aws.String("application/pdf"), }) +if err != nil { + log.Fatal(err) +} +``` + +### Download an object + +```go +import ( + "io" + "os" +) -// Download -result, _ := client.GetObject(ctx, &s3.GetObjectInput{ - Bucket: aws.String("my-bucket"), Key: aws.String("reports/report.pdf"), +result, err := client.GetObject(ctx, &s3.GetObjectInput{ + Bucket: aws.String("my-bucket"), + Key: aws.String("reports/report.pdf"), }) +if err != nil { + log.Fatal(err) +} defer result.Body.Close() -out, _ := os.Create("local-report.pdf") -io.Copy(out, result.Body) -// List (paginated) +out, err := os.Create("local-report.pdf") +if err != nil { + log.Fatal(err) +} +defer out.Close() +if _, err := io.Copy(out, result.Body); err != nil { + log.Fatal(err) +} +``` + +### List objects + +```go +import "fmt" + paginator := s3.NewListObjectsV2Paginator(client, &s3.ListObjectsV2Input{ Bucket: aws.String("my-bucket"), }) + for paginator.HasMorePages() { - page, _ := paginator.NextPage(ctx) + page, err := paginator.NextPage(ctx) + if err != nil { + log.Fatal(err) + } for _, obj := range page.Contents { - fmt.Println(*obj.Key, obj.Size) + // obj.Size is a *int64; dereference it with aws.ToInt64 to print the number + fmt.Println(*obj.Key, aws.ToInt64(obj.Size)) } } +``` -// Delete -client.DeleteObject(ctx, &s3.DeleteObjectInput{ - Bucket: aws.String("my-bucket"), Key: aws.String("reports/report.pdf"), +### Delete an object + +```go +_, err := client.DeleteObject(ctx, &s3.DeleteObjectInput{ + Bucket: aws.String("my-bucket"), + Key: aws.String("reports/report.pdf"), }) +if err != nil { + log.Fatal(err) +} ``` ## Presigned URLs ```go +import ( + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/service/s3" +) + presigner := s3.NewPresignClient(client) -downloadReq, _ := presigner.PresignGetObject(ctx, &s3.GetObjectInput{ - Bucket: aws.String("my-bucket"), Key: aws.String("reports/report.pdf"), +// Download URL valid for 1 hour +downloadReq, err := presigner.PresignGetObject(ctx, &s3.GetObjectInput{ + Bucket: aws.String("my-bucket"), + Key: aws.String("reports/report.pdf"), }, s3.WithPresignExpires(time.Hour)) +if err != nil { + log.Fatal(err) +} +fmt.Println(downloadReq.URL) -uploadReq, _ := presigner.PresignPutObject(ctx, &s3.PutObjectInput{ - Bucket: aws.String("my-bucket"), Key: aws.String("uploads/new-file.txt"), +// Upload URL valid for 15 minutes +uploadReq, err := presigner.PresignPutObject(ctx, &s3.PutObjectInput{ + Bucket: aws.String("my-bucket"), + Key: aws.String("uploads/new-file.txt"), }, s3.WithPresignExpires(15*time.Minute)) +if err != nil { + log.Fatal(err) +} +fmt.Println(uploadReq.URL) +``` + +## Error handling + +```go +import ( + "errors" + "fmt" + + "github.com/aws/smithy-go" +) + +_, err := client.GetObject(ctx, &s3.GetObjectInput{ + Bucket: aws.String("my-bucket"), + Key: aws.String("missing.txt"), +}) +if err != nil { + var apiErr smithy.APIError + if errors.As(err, &apiErr) { + fmt.Println(apiErr.ErrorCode(), apiErr.ErrorMessage()) + } +} ``` +See the [Error Reference](https://docs.filone.com/reference/errors) for a full list of error codes. + --- @@ -2976,25 +3482,24 @@ uploadReq, _ := presigner.PresignPutObject(ctx, &s3.PutObjectInput{ Source: https://docs.filone.com/sdk/cli -The AWS CLI works with Fil One out of the box. Install it, configure -credentials, and use --endpoint-url https://s3..filonecontent.com on every command -— or set it as a profile default. +The [AWS CLI](https://aws.amazon.com/cli/) works with Fil One out of the box. Install it, configure your credentials, and use `--endpoint-url https://s3..filonecontent.com` on every command — or set it as a profile default so you never have to type it. -Note: the endpoint depends on your bucket's region. Examples here use -eu-west-1, the default. For a bucket in us-east-1, use -https://s3.us-east-1.filonecontent.com and region us-east-1. The endpoint, the region, and -your access key must all refer to the same region — set up one profile per -region if you use both. +Note: The endpoint depends on your bucket's region +Examples here use `eu-west-1`, the default region. For a bucket in `us-east-1`, use `https://s3.us-east-1.filonecontent.com` and region `us-east-1`. The endpoint, the region, and your access key must all refer to the same region — set up one profile per region if you use both. ## Installation -Use AWS CLI v2. Version 1 (`pip install awscli`) does NOT read endpoint_url from -~/.aws/config, so the profile setup below silently won't work — install v2: +Use **AWS CLI v2**, version 2.13 or later, so the CLI reads `endpoint_url` from your profile. `pip install awscli` installs v1; install v2 instead: ```bash brew install awscli -# or follow the official installer for your platform +# or follow the official installer for your platform: +# https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html +``` +Confirm you have v2: + +```bash aws --version # should print aws-cli/2.x ``` @@ -3002,6 +3507,8 @@ aws --version # should print aws-cli/2.x ### Option 1: Named profile (recommended) +Add a `filone` profile to your AWS config files so you don't have to pass `--endpoint-url` on every command: + ```ini # ~/.aws/config [profile filone] @@ -3011,9 +3518,7 @@ s3 = addressing_style = path ``` -The `addressing_style = path` line is REQUIRED: Fil One only supports path-style -URLs, and the CLI defaults to virtual-hosted style even with a custom endpoint, -which fails with a DNS or 404-shaped error. +The `addressing_style = path` line is required: Fil One only supports path-style URLs, and the CLI defaults to virtual-hosted style even with a custom endpoint, which fails with a DNS or 404-shaped error. ```ini # ~/.aws/credentials @@ -3022,12 +3527,15 @@ aws_access_key_id = YOUR_ACCESS_KEY aws_secret_access_key = YOUR_SECRET_KEY ``` -Then use --profile filone (or AWS_PROFILE=filone) on every command: +Then use `--profile filone` (or `AWS_PROFILE=filone`) on every command: ```bash aws s3 ls --profile filone +``` -# Or set it for the shell session +Or set it for your shell session: + +```bash export AWS_PROFILE=filone aws s3 ls ``` @@ -3040,14 +3548,13 @@ export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY export AWS_DEFAULT_REGION=eu-west-1 ``` -There is no environment variable for addressing style, so set path-style once in -config (it applies to the `default` profile): +There is no environment variable for addressing style, so set path-style once in your config (it applies to the `default` profile): ```bash aws configure set default.s3.addressing_style path ``` -Then pass --endpoint-url on each command: +Then pass `--endpoint-url` on each command: ```bash aws s3 ls --endpoint-url https://s3.eu-west-1.filonecontent.com @@ -3057,62 +3564,70 @@ aws s3 ls --endpoint-url https://s3.eu-west-1.filonecontent.com ### Create a bucket -CreateBucket is region-dependent. It is NOT available in eu-west-1 — use the -dashboard there, via Buckets → Create bucket. In us-east-1, with a key that has -the CreateBucket permission: +`CreateBucket` is region-dependent. It is not available in `eu-west-1`: create the bucket in the [Fil One console](https://app.filone.com) there, with **New bucket**. In `us-east-1`, use a `us-east-1` profile (here `filone-us`, set up like `filone` above but with the `us-east-1` endpoint, region and key) whose key has the `CreateBucket` permission: ```bash -aws s3 mb s3://my-bucket --profile filone +aws s3 mb s3://my-bucket --profile filone-us ``` -Versioning and Object Lock can only be set when the bucket is created, and only -from the dashboard. +Versioning and Object Lock can only be set when the bucket is created, and only in the console. See [Buckets](https://docs.filone.com/storage/buckets). -### Upload, list, download, delete +### Upload a file ```bash -# Upload a file +# report.pdf is any local file aws s3 cp report.pdf s3://my-bucket/reports/report.pdf --profile filone +``` -# Upload a directory +### Upload a directory + +```bash aws s3 sync ./local-folder s3://my-bucket/folder/ --profile filone +``` -# List objects +### List objects + +```bash aws s3 ls s3://my-bucket/ --profile filone +# Recursive listing with sizes aws s3 ls s3://my-bucket/ --recursive --human-readable --profile filone +``` + +### Download a file -# Download a file +```bash aws s3 cp s3://my-bucket/reports/report.pdf ./report.pdf --profile filone +``` -# Download a directory +### Download a directory + +```bash aws s3 sync s3://my-bucket/folder/ ./local-folder --profile filone +``` + +### Delete an object -# Delete an object +```bash aws s3 rm s3://my-bucket/reports/report.pdf --profile filone ``` ### Delete a bucket -DeleteBucket support depends on the region. In us-east-1, an empty bucket can be -removed with a key that has the DeleteBucket permission: +`DeleteBucket` support depends on the region. In `us-east-1` you can remove an empty bucket with a `us-east-1` profile whose key has the `DeleteBucket` permission: ```bash -aws s3 rb s3://my-bucket --profile filone +aws s3 rb s3://my-bucket --profile filone-us ``` -In eu-west-1 the operation is not available over the S3 API. Delete the bucket -from the Fil One dashboard instead, via the bucket's actions menu in Buckets -(Owner and Admin roles only). +In `eu-west-1` the operation is not available over the S3 API. Delete the bucket from the [Fil One dashboard](https://app.filone.com) instead, via the bucket's actions menu in **Buckets** (Owner and Admin roles only). See [Buckets](https://docs.filone.com/storage/buckets#deleting-a-bucket). ## Multipart uploads -The AWS CLI handles multipart uploads automatically. The threshold is -configurable: +The AWS CLI handles multipart uploads automatically. You can configure the threshold: ```bash # Set multipart threshold to 100 MB (default is 8 MB) -# Note: use the bare "s3." key with --profile; the "default." prefix is only -# for the default profile +# Note: use the bare "s3." key with --profile; the "default." prefix is only for the default profile aws configure set s3.multipart_threshold 100MB --profile filone aws configure set s3.multipart_chunksize 50MB --profile filone ``` @@ -3131,6 +3646,8 @@ aws s3api abort-multipart-upload \ --profile filone ``` +See the [S3 Compatibility Reference](https://docs.filone.com/reference/s3-compatibility) for the full list of supported operations. + --- @@ -3138,80 +3655,69 @@ aws s3api abort-multipart-upload \ Source: https://docs.filone.com/faq -**Is Fil One S3-compatible?** -Yes. Any application, SDK, or tool that works with AWS S3 works with Fil One by -changing the endpoint URL to https://s3.eu-west-1.filonecontent.com. - -**Do I need to know anything about blockchain or cryptocurrency?** -No. Fil One is a standard cloud storage service. You sign up with an email, store -data using familiar S3 tools, and pay with a credit card. - -**Where is my data stored?** -You choose the region at bucket creation: eu-west-1 Europe (France) or us-east-1 -US East (Michigan). Objects stay in their bucket's region and the region cannot be -changed afterwards. Within a region, storage is fulfilled by a distributed network -of storage providers on Filecoin. All data is encrypted at rest. - -**What happens when I delete an object?** -On a bucket WITHOUT versioning: it disappears immediately, no recycle bin or undo. -On a bucket WITH versioning: a delete over the S3 API without a version ID places -a delete marker instead. The object stops appearing in listings but every prior -version is kept, downloadable by version ID, and the object can be made visible -again by deleting the delete marker. Retained versions still count as stored -storage. THE DASHBOARD IS DIFFERENT: it always permanently deletes the specific -version you chose and never writes a delete marker. - -**Can I migrate from AWS S3?** -Yes. Use aws s3 sync, rclone, or any S3-compatible transfer utility pointed at -the Fil One endpoint. - -**Do you charge for egress?** -On a paid plan, no — there are no egress or data transfer fees. The free trial is -the exception: it includes 2 TB of egress rather than unlimited. - -**What is included in the free trial?** -30-day trial with 1 TB storage, 2 TB egress, unlimited API operations. No credit -card required. - -**Can I use Fil One for backups?** -Fil One exposes an S3-compatible API, so backup software that targets S3 -generally works, but specific backup products have NOT been verified. Three -documented gaps are ones backup tools commonly depend on: server-side copy of a -SPECIFIC VERSION is unverified in eu-west-1 (CopyObject is confirmed in -us-east-1, and plain server-side copy works in eu-west-1, but copying a specific -VersionId has not been verified there; some tools use CopyObject for renames, -moves, dedupe); no -CreateBucket over the API in eu-west-1 (a tool that provisions its own -repository bucket needs it created in the dashboard first); and no lifecycle -rules (retention-based pruning must be handled by the tool). Path-style -addressing is required and bucket names cannot contain dots. - -**How does Filecoin protect the integrity of stored data?** -Built on Filecoin, where storage providers must continuously submit cryptographic -proofs (Proof of Replication and Proof of Spacetime) that they still hold the data -they committed to store, or face penalties. This runs at the network level and is -not something a customer triggers or checks. Fil One does not expose per-object -CIDs, deal IDs, or sealing state, so you cannot independently audit an individual -object today. For your own integrity checks, compare the ETag from HeadObject -against a checksum you keep, or use Object Lock for immutability. - -**What happens to my data if I delete it?** -Immediately removed from your Fil One account and no longer accessible. Because -Filecoin stores data in sealed sectors, the underlying storage may persist for a -bounded period until the sector naturally expires (duration set by the storage -layer), but the data is inaccessible from the moment of deletion. That residual -data stays encrypted, and key custody sits with the regional storage operator -rather than with you or Fil One. Note: account -closure does NOT purge data — the account is disabled and access blocked, and -no automatic purge runs; contact support to request removal. - -**Can multiple users access the same account?** -Yes, through organizations, which are in BETA and not yet enabled for every -account. An organization can have several members, each with a role: Owner, -Admin, Member, or Read only (see App: Organization). Access through the S3 API is -still per access key: there are no IAM users or bucket policies, so to share -limited access with other services, create API keys scoped to specific buckets -and permissions. +## Is Fil One S3-compatible? + +Yes. Fil One provides an S3-compatible API, and the standard S3 SDKs and tools work with it once you make two changes: set the endpoint to your region's (`https://s3.eu-west-1.filonecontent.com` or `https://s3.us-east-1.filonecontent.com`), and turn on path-style addressing. Some S3 features are not available, such as bucket policies and lifecycle rules. Check the [S3 Compatibility Reference](https://docs.filone.com/reference/s3-compatibility) for the operations your application uses. + +## Do I need to know anything about blockchain or cryptocurrency? + +No. Fil One is a standard cloud storage service. You sign up with an email, store data using familiar S3 tools, and pay with a credit card. The underlying storage infrastructure handles everything else transparently. + +## Where is my data stored? + +You choose the region when you create a bucket. Fil One currently offers **Europe (France)** as `eu-west-1` and **US East (Michigan)** as `us-east-1`. Objects in a bucket stay in that bucket's region, and the region cannot be changed afterwards, so pick it deliberately if data residency matters to you. + +Within a region, storage is fulfilled by a distributed network of storage providers on Filecoin. All data is encrypted at rest. See [Limits & Quotas](https://docs.filone.com/limits) for the region list and [Encryption](https://docs.filone.com/security/encryption) for how encryption is handled. + +## What happens when I delete an object or bucket? + +On a bucket **without versioning**, the object disappears from your account immediately and there is no recycle bin or undo. + +On a bucket **with versioning enabled**, a delete over the S3 API without a version ID places a delete marker instead. The object stops appearing in listings, but every prior version is kept and can still be downloaded by version ID, and you can make the object visible again by deleting the delete marker. Those retained versions continue to count as stored storage. Deleting from the dashboard is different: it always removes the specific version you chose, permanently, and never writes a delete marker. See [Versioning](https://docs.filone.com/storage/versioning). + +Once deleted, an object is no longer accessible through the API or the dashboard. Because Filecoin stores data in sealed sectors, the underlying storage may persist for a bounded period until the sector naturally expires — an infrastructure detail set by the storage layer, not a user-facing state. That residual data stays encrypted, with key custody held by the regional storage operator rather than by you or Fil One (see [Encryption](https://docs.filone.com/security/encryption)). The same applies when you delete a bucket. + +## Can I migrate from AWS S3? + +Yes. Because Fil One is S3-compatible, you can use standard migration tools like `aws s3 sync`, `rclone`, or any S3-compatible transfer utility. Point the tool at your Fil One endpoint and credentials (with path-style addressing enabled — see [SDKs & Tools](https://docs.filone.com/sdk/overview)). One naming caveat: Fil One does not allow dots in bucket names, so a bucket like `my.data.bucket` must be renamed during migration. + +## Do you charge for egress? + +On a paid plan, no. There are no egress or data transfer fees. + +The free trial is the exception: it includes 2 TB of egress rather than unlimited. See [Trial & Billing](https://docs.filone.com/billing/trial). + +## What is included in the free trial? + +The 30-day trial includes 1 TB of storage, 2 TB of egress bandwidth, and unlimited API operations. No credit card is required. See [Trial and Billing](https://docs.filone.com/billing/trial) for details. + +## Can I use Fil One for backups? + +Fil One exposes an S3-compatible API, so backup software that targets S3 generally works — but check your tool's requirements first. We have not verified specific backup products, and three of the documented gaps are ones backup tools commonly depend on: + +- **Server-side copy of a specific version is unverified in `eu-west-1`.** `CopyObject` is confirmed in `us-east-1`, and plain server-side copy works in `eu-west-1`, but copying a specific `VersionId` has not been verified there. Some tools use `CopyObject` for renames, moves, and deduplication. +- **No `CreateBucket` over the API in `eu-west-1`.** A tool that provisions its own repository bucket needs the bucket created in the dashboard first. +- **No lifecycle rules.** Retention-based pruning has to be handled by the tool itself. + +Path-style addressing is also required, and bucket names cannot contain dots. Check your tool against the [S3 Compatibility Reference](https://docs.filone.com/reference/s3-compatibility) before committing to it. + +## What durability guarantees do you offer? + +Fil One is designed for high durability through distributed storage across multiple providers. We don't publish a durability figure; for details, email [support@filone.com](mailto:support@filone.com). + +Availability is covered separately: the [Fil One SLA](https://www.filone.com/sla) commits to 99.9% monthly uptime, with service credits if it is missed. + +## Can multiple users access the same account? + +Yes, through organizations. An organization can have several members, each with a role: **Owner**, **Admin**, **Member**, or **Read only**. See [Organization](https://docs.filone.com/app/organization) and [Roles and permissions](https://docs.filone.com/app/organization#roles-and-permissions). + +Access through the S3 API is still per access key. There are no IAM users or bucket policies, so to share limited access with other services, create API keys scoped to specific buckets and permissions. + +## How does Filecoin protect the integrity of stored data? + +Fil One is built on Filecoin, a distributed storage network where storage providers must continuously submit cryptographic proofs — called Proof of Replication (PoRep) and Proof of Spacetime (PoSt) — to prove they are still holding the data they committed to store. Providers that fail to produce valid proofs are penalised. This proof cycle runs at the network level and is not something you trigger or check yourself. + +Fil One does not currently expose per-object proof data — content identifiers, deal IDs, and sealing state are not surfaced through the API or the dashboard, so you cannot independently audit an individual object today. For object-level integrity checks in your own application, compare the `ETag` returned by `HeadObject` against a checksum you keep, or apply [Object Lock](https://docs.filone.com/storage/object-lock) to make objects immutable for a fixed retention period. --- @@ -3220,31 +3726,22 @@ and permissions. Source: https://docs.filone.com/limits -## Account limits +## Organization limits | Limit | Trial | Paid | |-------|-------|------| | Storage | 1 TB (1,000 GB) | No limit | | Egress bandwidth | 2 TB (cumulative over the trial) | No limit | | API operations | Unlimited | Unlimited | -| Buckets per account | — | 100 in eu-west-1, 300 in us-east-1 | +| Buckets per organization | Not confirmed | 100 in `eu-west-1`, 300 in `us-east-1` | -During the trial the storage cap write-locks the account and the egress cap -disables it; trial egress is a single cumulative budget for the 30 days. The -bucket limit is provisioned per account rather than fixed by plan, and differs by -region: on a paid plan it is 100 buckets in eu-west-1 and 300 in us-east-1. -Contact support if you need a higher limit. +During the trial these two caps behave differently: reaching the **storage** cap **write-locks** the account (reads still work), while reaching the **egress** cap **disables** it entirely. Trial egress is a single cumulative budget for the whole 30 days, not a monthly amount that resets. See [Trial & Billing](https://docs.filone.com/billing/trial). -## Regions +The bucket limit is provisioned per organization rather than fixed by plan, and it differs by region. On a **paid** plan it is **100 buckets in `eu-west-1`** and **300 in `us-east-1`**. To ask for a higher limit, email [support@filone.com](mailto:support@filone.com). -| Region | Identifier | Status | -|--------|------------|--------| -| Europe (France) | eu-west-1 | Available (default) | -| US East (Michigan) | us-east-1 | Available | +Each person can own up to **10 organizations**, and each organization can have up to **25 pending invitations** at a time. See [Organization](https://docs.filone.com/app/organization). -The region is selected at bucket creation time and cannot be changed afterward. -Access keys are also scoped to a single region. Bucket creation and deletion -through the S3 API are available in us-east-1 but not in eu-west-1. +The trial lasts 30 days. After it ends, your account enters a 7-day read-only grace period. If you do not upgrade before the grace period ends, the account is disabled and access is blocked. See [Trial & Billing](https://docs.filone.com/billing/trial) for the full timeline and email schedule. ## Object limits @@ -3258,26 +3755,47 @@ through the S3 API are available in us-east-1 but not in eu-west-1. | Maximum object key length | 1,024 characters in the dashboard; 1,024 bytes (standard S3 limit) through the API | | Maximum metadata size per object | 2 KB | -Only the DASHBOARD key-length check is code-backed: the dashboard rejects object -keys longer than 1,024 CHARACTERS on upload. The other values (the 1,024-byte key -length through the S3 API, object and part sizes, part count, minimum part size, -metadata size) are standard AWS S3 limits that the gateway is expected to follow -but that are NOT independently confirmed — treat them as guidance. +Note: Which of these are Fil One-specific +The **dashboard** rejects object keys longer than **1,024 characters** when you upload, which is verified in code. The other values in this table (the 1,024-byte key length through the S3 API, maximum object and part sizes, maximum part count, minimum part size, and metadata size) are the **standard AWS S3 limits** that Fil One's storage gateway is expected to follow but that we have **not independently confirmed**. Treat them as guidance rather than guaranteed values, and test against your own workload before hard-coding an exact figure. + +For objects larger than 5 GB, use [multipart upload](https://docs.filone.com/storage/multipart-uploads). + +## Console limits + +These apply in the [console](https://docs.filone.com/app/buckets) at app.filone.com, in both regions. They are set in the console, so they don't apply to requests you make with an S3 SDK or the AWS CLI. + +| Limit | Value | +|-------|-------| +| File size for a console upload | 5 GB. The console uploads each file in a single request. Use the [AWS CLI](https://docs.filone.com/sdk/cli) or an SDK for larger files. | +| Tags per console upload | 50, up to 128 characters each | +| Description per console upload | 1,000 characters | +| Share link expiry | 7 days at most | +| Default retention on a bucket | 1 day to 100 years (36,500 days) | + +## Regions + +| Region | Identifier | Status | +|--------|------------|--------| +| Europe (France) | `eu-west-1` | Available (default) | +| US East (Michigan) | `us-east-1` | Available | + +The region is selected at bucket creation time and cannot be changed afterward. Access keys are also scoped to a single region — see [API Keys](https://docs.filone.com/security/api-keys). + +Bucket creation and deletion through the S3 API are available in `us-east-1` but not in `eu-west-1`. See [Buckets](https://docs.filone.com/storage/buckets). ## API rate limits -Rate limits are enforced by the underlying storage gateway. If you encounter -SlowDown or ServiceUnavailable responses, use exponential backoff. Contact -support if you are consistently hitting limits at scale. +Rate limits are enforced by the underlying storage gateway. Fil One does not impose additional rate limits on top of these. If you encounter `SlowDown` or `ServiceUnavailable` responses, back off with exponential retry. If you consistently hit limits at scale, email [support@filone.com](mailto:support@filone.com). ## Naming constraints -**Bucket names:** 3-63 characters, lowercase letters/numbers/hyphens (no dots, -unlike AWS S3), must start and end with a letter or number, unique within Fil One. - -**Object keys:** Up to 1,024 characters for dashboard uploads; through the S3 -API, the standard S3 limit of 1,024 bytes (UTF-8) applies but is not -independently confirmed. Avoid control characters and characters -requiring special URL encoding for best compatibility. +**Bucket names:** +- 3-63 characters +- Lowercase letters, numbers, hyphens (no dots — Fil One's naming rules are stricter than AWS S3 here) +- Must start and end with a letter or number +- Must not start with `filone-rag-`, which is reserved +- Unique within Fil One ---- +**Object keys:** +- Up to 1,024 characters for dashboard uploads; through the S3 API, the standard S3 limit of 1,024 bytes (UTF-8) applies but is not independently confirmed +- Any UTF-8 character is valid, but avoid control characters and characters that require special URL encoding for best compatibility diff --git a/static/llms.txt b/static/llms.txt index 8b91055..bbc712b 100644 --- a/static/llms.txt +++ b/static/llms.txt @@ -1,13 +1,14 @@ # Fil One Documentation -> Fil One is S3-compatible object storage built for AI agents and data-intensive -> workloads. Stored on the Filecoin network, where storage providers must +> Fil One is an S3-compatible object storage platform for teams that need +> reliable, cost-effective storage. Stored on the Filecoin network, where storage providers must > continuously submit cryptographic proofs that they still hold the data they > committed to store. No egress fees on paid plans, no per-request charges, > $5.99/TB/month with a $5.99/month minimum. -> Use any S3-compatible SDK or tool — point it at your region's endpoint, -> `https://s3..filonecontent.com`, with standard Access Key ID / Secret Access Key -> auth. Endpoint, region and key must all refer to the same region. +> Standard S3 SDKs and tools work once you point them at your region's endpoint, +> `https://s3..filonecontent.com`, and enable path-style addressing, with +> standard Access Key ID / Secret Access Key auth. Some S3 features are missing +> (see S3 Compatibility). Endpoint, region and key must all refer to the same region. Critical integration notes for developers: - CreateBucket and DeleteBucket via the S3 API are region-dependent: supported @@ -18,17 +19,28 @@ Critical integration notes for developers: (virtual-hosted-style URLs are not supported) - Access keys are scoped to ONE region and cannot be used against another - Region, versioning, Object Lock and retention are fixed at bucket creation and - cannot be changed afterwards (no update-bucket operation) -- Authentication: AWS Signature Version 4 (SigV4) — all S3-compatible SDKs - handle this automatically + cannot be changed afterwards (no update-bucket operation). PutBucketVersioning, + PutBucketObjectLockConfiguration and Get/PutBucketEncryption CANNOT BE GRANTED + to any access key in either region; versioning and default retention are set + only in the console's create form (under Advanced settings) +- Bucket names are unique within the region; names starting with `filone-rag-` + are reserved +- Authentication: AWS Signature Version 4 (SigV4). In boto3 set + `Config(signature_version="s3v4")` explicitly so presigned URLs use SigV4 +- AWS SDK for JavaScript v3.729+ adds CRC32 checksums by default; set + `requestChecksumCalculation: "WHEN_REQUIRED"` and + `responseChecksumValidation: "WHEN_REQUIRED"` on the S3Client, or presigned + uploads fail with BadDigest +- Credentials: the console's Download .env uses the standard AWS_ACCESS_KEY_ID / + AWS_SECRET_ACCESS_KEY names, which every SDK reads automatically - All buckets are private by default; all data is encrypted at rest and in transit (TLS); encryption cannot be disabled. At-rest encryption is done by the regional storage gateway and keys are held by the regional operator, NOT by Fil One and NOT customer-managed. Do not name a specific cipher or SSE mode. SSE-KMS is rejected in BOTH regions (InvalidRequest in us-east-1; AccessDenied - or InvalidRequest in eu-west-1) and SSE-C is unsupported — send no encryption - headers at all. In eu-west-1, Get/PutBucketEncryption also return AccessDenied, - so no encryption configuration can be read or written there + or InvalidRequest in eu-west-1). SSE-C is rejected in eu-west-1 and not yet + confirmed in us-east-1 — send no encryption headers at all. No access key can + be granted Get/PutBucketEncryption in either region - Regions: eu-west-1 Europe (France, default) and us-east-1 US East (Michigan) - Deletion is permanent and immediate on non-versioned buckets (no recycle bin). On versioned buckets an S3-API delete WITHOUT a version ID places a delete @@ -37,23 +49,25 @@ Critical integration notes for developers: the specific version on the row chosen, even on a versioned bucket - CopyObject / server-side copy is confirmed working in us-east-1, including copying a specific version onto the current key to promote it (a version - restore). In eu-west-1 PLAIN COPY WORKS but the version-id form is UNVERIFIED - (the harness cannot configure versioning over the API there); download and - re-upload is the fallback. The dashboard has no restore/roll-back button either way + restore). In eu-west-1 PLAIN COPY WORKS but the version-id form is NOT YET + CONFIRMED; download and re-upload is the fallback. The dashboard has no restore/roll-back button either way - Per-object CIDs, deal IDs, and sealing state are NOT exposed — customers cannot independently audit an individual object - A failed payment (past_due) makes the DASHBOARD READ-ONLY from the moment the - payment fails, not after a later deadline; Stripe retries the charge + payment fails, not after a later deadline; Stripe retries the charge. An + organization OWNER can reactivate a canceled or disabled subscription from + Billing -> Reactivate (no need to contact support) - Trial caps are enforcement thresholds, not allowances: storage reaching 1 TB WRITE-LOCKS the account (lifted on the next usage run once storage is back under 1 TB); egress reaching 2 TB DISABLES it entirely, with NO read-only grace period first. Trial egress is a single cumulative budget over the 30 days. Enforced by a twice-daily job (~07:00/19:00 UTC), not in real time - Storage is DECIMAL: 1 TB = 1,000 GB, 1 GB = 1,000,000,000 bytes -- Governance Object Lock has NO grantable bypass permission in the product +- Object Lock has NO grantable bypass permission: retention can be set or + EXTENDED but NEVER SHORTENED, in either mode - PutObjectRetention (per-object retention) and Legal Hold - (Get/PutObjectLegalHold) work in BOTH REGIONS, including Governance-mode bypass - and blocking delete while a hold is active. Both need the matching granular key + (Get/PutObjectLegalHold) work in BOTH REGIONS, including blocking delete while + a hold is active. Both need the matching granular key permission, which is never granted automatically, and only an organization OWNER can create a key with PutObjectRetention or PutObjectLegalHold. Evidence differs by region: us-east-1 from the automated compatibility suite, @@ -61,8 +75,8 @@ Critical integration notes for developers: bucket there) - The S3 API has NO IAM users, roles, or bucket policies: each request is allowed or refused by the access key's own permissions and bucket scope. The CONSOLE - has organizations (BETA) with four member roles (Owner, Admin, Member, Read - only); a key can only carry permissions its creator's role holds + has organizations with four member roles (Owner, Admin, Member, Read only); a + key can only carry permissions its creator's role holds - Access keys can be ROTATED in the dashboard (new Access Key ID and secret, same name/permissions/buckets/region/expiry; old secret stops working at once) - Object/part size limits (5 TB object, 5 GB single-PUT, 10,000 parts, 5 MB min @@ -72,9 +86,10 @@ Critical integration notes for developers: S3 limit of 1,024 bytes applies but is NOT independently confirmed - In eu-west-1, UNIMPLEMENTED OPERATIONS RETURN AccessDenied (403), NOT NotImplemented (501), and a bucket/key you cannot see returns 403 instead of - 404. A 403 from PutBucketVersioning, PutBucketPolicy, PutBucketAcl, - PutBucketEncryption, PutBucketLifecycleConfiguration or the tagging operations - means the FEATURE IS ABSENT, not that the key lacks a permission + 404. A 403 from PutBucketPolicy, PutBucketAcl, PutBucketLifecycleConfiguration + or the tagging operations means the FEATURE IS ABSENT, not that the key lacks + a permission; PutBucketVersioning and PutBucketEncryption can't be granted to + any key, so they fail the same way - ACL requests fail two different ways in eu-west-1: a canned-ACL HEADER on an upload (--acl public-read) is SILENTLY IGNORED and the upload SUCCEEDS, while a DEDICATED call (Put/GetBucketAcl, Put/GetObjectAcl) is REJECTED with @@ -91,87 +106,105 @@ Critical integration notes for developers: ## Getting Started -- [Quickstart](https://docs.filone.com/quickstart): Create an account, generate - API keys, and upload your first object — covers App, AWS CLI, Python, and - JavaScript paths -- [Quickstart - AWS CLI](https://docs.filone.com/quickstart/cli): Full CLI walkthrough - including named profile setup to avoid repeating --endpoint-url +- [Introduction](https://docs.filone.com/): What Fil One is, who it is for, and + where to start +- [Quickstart](https://docs.filone.com/quickstart): Create an account (email, + Google, or GitHub), create a bucket in the console (leave Advanced settings at + their defaults for a first bucket), create an API key, and upload your first + object — covers App, AWS CLI (a `filone` profile, not your default one), + Python, and JavaScript paths +- [Quickstart - AWS CLI](https://docs.filone.com/quickstart/cli): AWS CLI v2.13+ + with a named `filone` profile holding endpoint_url and path-style addressing; + `my-bucket` throughout; CreateBucket from the CLI only with a us-east-1 + profile (`filone-us`) - [Quickstart - SDK](https://docs.filone.com/quickstart/sdk): Copy-paste examples - for Python (boto3), JavaScript (AWS SDK v3), and Go to create a bucket, upload, - and verify + for Python (boto3), JavaScript (AWS SDK v3, saved as `upload.mjs`), and Go + (`go mod init` first) that upload and verify; create the bucket in the + console first. Credentials come from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY ## Storage -- [Buckets](https://docs.filone.com/storage/buckets): Bucket naming rules, how to - create via dashboard, listing via API, deleting (bucket must be EMPTY; dashboard - delete works in every region for Owner/Admin roles; S3-API DeleteBucket in - us-east-1 only), and Filecoin deal lifecycle on deletion +- [Buckets](https://docs.filone.com/storage/buckets): Naming rules (no dots; + unique within the region; `filone-rag-` prefix reserved), creating in the + console (Versioning, Object Lock and Retention under Advanced settings, only at + creation; Retention starts at 15 days Governance), listing via API, deleting + (bucket must be EMPTY; console delete works in every region for Owner/Admin + roles; S3-API DeleteBucket in us-east-1 only), and what happens to deleted data - [Objects](https://docs.filone.com/storage/objects): Upload, download, list, delete, - and presigned URL generation with code examples for App, AWS CLI, and boto3. - Dashboard has multi-select delete and Empty bucket; a dashboard delete on a + and presigned URLs with code for App, AWS CLI, and boto3. A console delete on a versioned bucket PERMANENTLY removes that version (no delete marker), while an - S3-API delete without a version ID writes a delete marker + S3-API delete without a version ID writes a delete marker. A presigned URL is + a bearer credential until it expires; console Share links last at most 7 days - [Multipart Uploads](https://docs.filone.com/storage/multipart-uploads): Required above the single-PUT ceiling (standard S3 5 GB, not independently confirmed); - recommended for > 100 MB. Dashboard uploads are single-PUT; multipart is via + recommended for > 100 MB. Console uploads are single-PUT; multipart is via your own SDK/CLI. No lifecycle rule to auto-abort incomplete uploads. Cleanup needs List (list uploads) and Write (abort); us-east-1 keys created before 26 August 2026 lack these multipart actions (403), so replace them - [Versioning](https://docs.filone.com/storage/versioning): Opt-in at bucket - creation, cannot be suspended. S3-API delete without a version ID writes a - delete marker; the DASHBOARD NEVER DOES, it permanently deletes the chosen - version. Version operations need granular key permissions (List object - versions, Read object versions, Delete object versions), none granted + creation, cannot be suspended. Overwrites and S3-API deletes without a version + ID keep earlier versions; deleting a specific version, including any console + delete, is permanent. Version operations need granular key permissions (List + object versions, Read object versions, Delete object versions), none granted automatically - [Object Lock](https://docs.filone.com/storage/object-lock): WORM retention. Opt-in at bucket creation, Governance (default) and Compliance modes, 1 day to - 100 years, no trial-specific cap. NO third-party compliance attestation, NO - grantable Governance bypass permission in the product. Per-object - PutObjectRetention and Legal Hold work in both regions. - Regulations (SEC 17a-4, FINRA, HIPAA) are illustrative - use cases, not a certification claim + 100 years. NO grantable bypass permission, so retention can be set or extended + but NOT SHORTENED in either mode; Compliance retention can't be removed and + stays billed until it expires. Per-object PutObjectRetention and Legal Hold + work in both regions; Set retention / Set legal hold are Owner-only to grant. + NO third-party compliance attestation; regulations such as SEC 17a-4 are + illustrative use cases, not a certification claim ## Security - [Account Security](https://docs.filone.com/security/account-security): securing the account you sign in with (distinct from API request auth). Sign-in via - passkeys (primary), Google, GitHub, or email with password; email - verification is mandatory before the dashboard opens. Opt-in two-factor with - three factor types: authenticator app (OTP), security key (WebAuthn roaming), - device biometrics (WebAuthn platform). SMS and email codes are deliberately - NOT offered. Up to 20 passkeys per account. Single-use recovery codes. - Removing a factor or passkey, removing all factors, and regenerating a - recovery code all require a session established with 2FA or a passkey - (step-up). Transferring organization ownership also needs a sign-in within the - last five minutes (with 2FA or a passkey if 2FA is set up) + passkeys, Google, GitHub, or email with password; email verification is + mandatory before the console opens. Opt-in two-factor with three factor types: + authenticator app (OTP), security key, device biometrics. SMS and email codes + are deliberately NOT offered. Up to 20 passkeys per account. Single-use + recovery codes; signing in with one makes you set up a new two-factor method + in the same sign-in. Removing a factor or passkey, removing all factors, and + regenerating a recovery code require a session established with 2FA or a + passkey (step-up). Transferring organization ownership also needs a sign-in + within the last five minutes - [Authentication](https://docs.filone.com/security/authentication): SigV4 auth - setup for AWS CLI, Python (boto3), JavaScript (AWS SDK v3), and Go; credential - best practices including environment variable usage + setup for AWS CLI, Python (boto3 with signature_version s3v4), JavaScript + (AWS SDK v3), and Go; credentials from the standard AWS_* environment variables; + the Access Key ID identifies the key - [API Keys](https://docs.filone.com/security/api-keys): Creating keys with scoped - permissions (Read/Write/List/Delete), CreateBucket/DeleteBucket and - GetBucketVersioning/GetBucketObjectLockConfiguration groups, single-region - scoping, bucket-level scoping, key expiration, ROTATION, revocation, best - practices. Read in us-east-1 also includes ListBucket (not in eu-west-1); Write - without Delete can still OVERWRITE. A key can only carry permissions its - creator's organization role holds; PutObjectRetention/PutObjectLegalHold are - Owner-only. Names starting with `filone-console` are reserved + permissions (Read/Write/List/Delete; Read, Write, List and the bucket-config + reads are pre-selected, so untick Write for read-only keys), single-region + scoping, bucket-level scoping ("all buckets" means all in the key's region), + expiry (a key works through the end of the chosen UTC day), ROTATION, + revocation, handling downloaded .env/.csv files, best practices. Write without + Delete can still OVERWRITE; multipart uploads need Write. A key is capped at + its creator's role; removing a member or narrowing a role revokes their keys + that exceed it, and they are emailed which keys. Names starting with + `filone-console` are reserved - [Encryption](https://docs.filone.com/security/encryption): server-side - encryption always on by default for all objects; TLS in transit; keys held by - the regional operator (no customer-managed keys, cipher unconfirmed). + encryption always on for all objects; TLS in transit; keys held by the regional + operator (no customer-managed keys, cipher unconfirmed). SSE-KMS rejected in + both regions; SSE-C rejected in eu-west-1, not yet confirmed in us-east-1. Client-side encryption is up to you — AWS's S3 Encryption Client exists only for Java/.NET/Go/Ruby, NOT boto3/CLI/JS v3 ## Billing - [Trial & Billing](https://docs.filone.com/billing/trial): 30-day free trial with - 1 TB storage (1,000 GB) and 2 TB egress (cumulative); the trial starts after - EMAIL VERIFICATION, one trial per email address, invited members get none; - storage cap write-locks, egress cap disables the account directly (no - read-only grace first); trial lifecycle (active → grace → expiry); a failed - payment makes the dashboard read-only immediately; Pay as you go + 1 TB storage (1,000 GB) and 2 TB egress (cumulative); starts after EMAIL + VERIFICATION; ONE TRIAL PER PERSON, on the first organization they own — + organizations created later have no trial, need a payment method and are + billed separately with their own $5.99 minimum. Storage cap write-locks, egress + cap disables the account; S3 uploads can continue up to ~12 hours after the + trial ends until the twice-daily job applies read-only. A failed payment makes + the console read-only immediately. An Owner can REACTIVATE from Billing at any + time, even after the account is disabled (support is only for data removal). + Invoices are charged automatically to the card on file. Pay as you go $5.99/TB/month, $5.99/month minimum, no egress or request fees (earlier - subscribers keep their $4.99 or per-unit terms); Business plan - (1, 3, or 5-year terms) via sales. Cancellation is via the Stripe portal + subscribers keep their $4.99 or per-unit terms); Business plan (1, 3, or 5-year + terms) via sales. Cancellation is via the Stripe portal, Owners only - [Pricing](https://docs.filone.com/billing/pricing): Pay as you go $5.99/TB/month (decimal TB, 1,000 GB) with a $5.99/month minimum; single linear rate plus a floor (no first-TB tier); storage measured as daily readings and averaged, with @@ -179,148 +212,149 @@ Critical integration notes for developers: Organizations that subscribed before the move to $5.99 keep $4.99/TB with a $4.99 minimum; accounts predating any minimum have none - [Usage](https://docs.filone.com/billing/usage): What is measured (average stored - bytes, egress), trial caps and how they are enforced; the storage write-lock - lifts on the next usage run once storage is back under 1 TB. Billing page - visible to Owners and Admins + bytes, egress), which egress figure is which (billing period vs the Dashboard's + rolling 30 days vs the trial's cumulative total), trial caps and how they are + enforced; the billing date is the date you upgraded or last reactivated ## API Reference - [API Reference Overview](https://docs.filone.com/reference/overview): Base endpoint, SigV4 authentication requirement, path-style addressing, and response format - [S3 Compatibility](https://docs.filone.com/reference/s3-compatibility): Full table - of supported vs. unsupported S3 operations (GetObject, PutObject, DeleteObject, - ListObjectsV2, multipart, presigned URLs all supported; bucket policies, lifecycle - rules, IAM users/roles/bucket policies on the S3 API not yet supported; access - is per access key permissions and bucket scope); how unsupported operations respond in eu-west-1 - (AccessDenied, not NotImplemented); known error-code deviations and known - behavioral issues in eu-west-1; differences from AWS S3 + of supported vs. unsupported S3 operations per region (GetObject, PutObject, + DeleteObject, ListObjectsV2, multipart, presigned URLs supported; bucket + configuration calls such as PutBucketVersioning, PutBucketObjectLockConfiguration + and Get/PutBucketEncryption not available to access keys; bucket policies, + lifecycle rules and IAM users/roles not supported on the S3 API); how + unsupported operations respond in eu-west-1 (AccessDenied, not + NotImplemented); known error-code deviations and known issues; the JS SDK + checksum setting for presigned uploads - [Error Reference](https://docs.filone.com/reference/errors): Standard S3 XML error - format, full table of 4xx and 5xx error codes, the ways codes deviate from AWS, - console errors (account/region still being set up: 503; role does not permit - the action: 403), and troubleshooting for the most common errors - (SignatureDoesNotMatch, AccessDenied, ServiceUnavailable) + format, 4xx and 5xx error codes, the ways codes deviate from AWS, console + errors, and troubleshooting for first-request problems (key used in the wrong + region, virtual-hosted DNS failures, AccessDenied on delete because Delete is + not pre-selected, BadDigest on JS presigned uploads, multipart cleanup on old + us-east-1 keys). Service status: https://status.filone.com +- [Limits & Quotas](https://docs.filone.com/limits): Organization limits (storage, + egress, buckets per organization, 10 owned organizations, 25 pending + invitations), object size limits (max 5 TB, multipart above 5 GB; not + independently confirmed), console limits (5 GB per upload, 50 tags, + 1,000-character description, share links up to 7 days, retention 1 day to 100 + years), API rate limits, and naming constraints (reserved `filone-rag-` bucket + prefix; object keys 1,024 characters in the console, 1,024 bytes via the API) ## SDKs & Tools - [SDKs & Tools Overview](https://docs.filone.com/sdk/overview): Connection parameters - for all tools (endpoint, region, credentials); recommended tools list including - rclone, Cyberduck, s3cmd, MinIO Client + for all tools (endpoint, region, credentials from API Keys in the console; AWS + CLI v2.13+); recommended tools list including rclone, Cyberduck, s3cmd, MinIO + Client - [Python (boto3)](https://docs.filone.com/sdk/python): Full examples for upload, - download, list, delete, multipart, presigned URLs, and error handling + download, list, delete, multipart, presigned URLs (signature_version s3v4), and + error handling; CreateBucket only with a us-east-1 client - [JavaScript (AWS SDK v3)](https://docs.filone.com/sdk/javascript): Full examples - for Node.js including streaming downloads, pagination, presigned URLs, and - error handling; requires `forcePathStyle: true` + for Node.js (ES modules) including streaming downloads, pagination, presigned + URLs, and error handling; requires `forcePathStyle: true` and, for presigned + uploads on v3.729+, `requestChecksumCalculation: "WHEN_REQUIRED"` - [Go (aws-sdk-go-v2)](https://docs.filone.com/sdk/go): Full examples for upload, download, paginated listing, presigned URLs, and error handling; requires - `UsePathStyle: true` -- [AWS CLI](https://docs.filone.com/sdk/cli): Installation, named-profile - configuration, core operations, multipart uploads and cleanup. `aws s3 rb` - works in us-east-1 only; in eu-west-1 delete buckets from the dashboard - (Owner and Admin roles) + `UsePathStyle: true`; CreateBucket only with a us-east-1 client +- [AWS CLI](https://docs.filone.com/sdk/cli): Installation (v2.13+), named-profile + configuration, core operations, multipart uploads and cleanup. `aws s3 mb` and + `aws s3 rb` work in us-east-1 only (shown with a `filone-us` profile); in + eu-west-1 create and delete buckets in the console (Owner and Admin roles) -## Optional +## Console The browser console at app.filone.com, one page per console screen. No code required. Each page below is console-specific; the capability pages (Storage, Security, Billing) hold the concepts and code samples. -- [App - Dashboard](https://docs.filone.com/app/dashboard): Console home. Quick - setup checklist, PLAN/STORAGE/EGRESS cards (PLAN shown to Owner/Admin only), - Usage Trends (Storage area chart with latest reading; Egress bar chart with - the window total), Recent Activity. Storage is a periodic point-in-time reading - (a very recent change may not show yet) and egress is a rolling 30-day total, - not a calendar month. "Est. monthly cost" applies your plan's per-TB price to - the latest reading with the monthly minimum as the floor (not shown without a - per-TB rate), while the invoice uses AVERAGE storage, so they differ. Recent - Activity covers bucket and key creation; object-level events are not included - yet -- [App - Buckets](https://docs.filone.com/app/buckets): Bucket list (Name, Region, - Created; sorted by name; search, sortable columns and region filter from 5 - buckets), create form, object browser, upload, object detail, download/share, - delete. DELETE BUCKET from the row's actions menu: Owner/Admin only, EMPTY - buckets only, works in EVERY region including eu-west-1 (where S3-API - DeleteBucket is unavailable). "Empty bucket" removes every object, version and - delete marker server-side. Multi-select delete via checkboxes. A console delete - on a versioned bucket PERMANENTLY deletes the chosen version (NO delete - marker). Property cards: Versioning, Object Lock, Retention (no Encryption - card; always on). Name, region, versioning, Object Lock and default retention - are PERMANENT at creation (no update-bucket op). Upload is single-PUT (5 GB - ceiling); folder uploads skip system files; the browser shows the first ~1,000 - entries and the tab count is a daily reading that can lag; no version - restore/promote (download and re-upload). Download works on trial; SHARING IS - A PAID-PLAN FEATURE -- [App - API Keys](https://docs.filone.com/app/api-keys): Key list (Name, Region, - Buckets, Permissions, Created by, Status, Last Used) and create flow. Region is - REQUIRED (pre-set to eu-west-1) and a key is scoped to its own region's - endpoint. Read/Write/List pre-selected, Delete NOT; finer-grained permissions - (retention, legal hold, versions) are granted INDIVIDUALLY, so Write alone - cannot set retention. "Create bucket"/"Delete bucket" unavailable in - eu-west-1. Role ceiling: Read only cannot create keys, Members manage only - their own, Admins/Owners manage all; Set retention/Set legal hold are - Owner-only. `filone-console` name prefix reserved. Secret shown ONCE (at - creation or rotation) and never stored. ROTATE gives a new Access Key ID and - secret keeping name, permissions, buckets, region and expiry; the old secret - stops working at once; expired keys can't be rotated. Delete is the - revocation. "Last Used" and "Status" are placeholder columns reading - "Never"/"Active" for every key, and expiry is not shown after creation +- [App - Dashboard](https://docs.filone.com/app/dashboard): Console home. A new + organization opens on a Get started page (/get-started) with Create bucket and + Create API key. A dismissible Free trial banner shows days left and Upgrade. + PLAN/STORAGE/EGRESS cards (PLAN shown to Owner/Admin only), Usage Trends, + Recent Activity. Storage is a periodic point-in-time reading and egress is a + rolling 30-day total, not a calendar month. "Est. monthly cost" applies your + plan's per-TB price to the latest reading with the monthly minimum as the + floor, while the invoice uses AVERAGE storage, so they differ +- [App - Buckets](https://docs.filone.com/app/buckets): Bucket list, create form + (name unique in the region; Versioning, Object Lock and Retention under a + collapsed Advanced settings with "Needs Versioning" / "Needs Object Lock" + badges; only a Create bucket button; the new bucket's page then offers Create + API key), object browser, upload, object detail, download/share, delete. + DELETE BUCKET: Owner/Admin only, EMPTY buckets only, works in EVERY region. + EMPTY BUCKET permanently deletes every object, version and delete marker not + under retention or legal hold and cannot be undone. A console delete on a + versioned bucket PERMANENTLY deletes the chosen version (NO delete marker). + Name, region, versioning, Object Lock and default retention are PERMANENT at + creation. Upload is single-PUT (5 GB ceiling); the browser shows the first + ~1,000 entries; no version restore/promote. Download works on trial; SHARING IS + A PAID-PLAN FEATURE (links of 1 hour to 7 days) +- [App - API Keys](https://docs.filone.com/app/api-keys): Key list (Status Active + or Expired; Permissions as Read/Write/List/Delete badges plus +n; search and + region/status filters from 5 keys; a row opens a details panel with expiry, + region, buckets and full permissions; multi-select bulk delete) and create + flow. Region is REQUIRED and a key works only against its own region's + endpoint. Read/Write/List and the bucket-config reads pre-selected, Delete NOT; + retention, legal hold and version permissions are granted INDIVIDUALLY. + "Create bucket"/"Delete bucket" unavailable in eu-west-1. Role ceiling: Read + only cannot create keys, Members manage only their own, Admins/Owners manage + all; Set retention/Set legal hold are Owner-only. Secret shown ONCE (at + creation or rotation); downloaded .env/.csv files hold it in plain text, so + delete them and never commit them. ROTATE keeps name, permissions, buckets, + region and expiry; the old secret stops working at once. Deleting a key is the + revocation and breaks any application using it immediately - [App - AI Agent Toolkit](https://docs.filone.com/app/ai-agent-toolkit): NOT - RELEASED. A "Coming Soon" page introducing the toolkit plus a waitlist form, so - there is nothing to set up on it yet. What DOES work today: ordinary S3 access - keys scoped to a bucket, which is how LangChain, LlamaIndex, Vercel AI SDK and - CrewAI connect -- [App - Organization](https://docs.filone.com/app/organization): BETA. Every - account starts as a one-person organization with you as Owner. The - ORGANIZATION MENU at the top of the sidebar opens separate pages, each shown - only to roles that can use it: Edit organization (/edit-organization; name, - logo, and an Owner-only Danger zone), Members (/members; Members and - Invitations tabs), Billing (/billing), and Audit log (/audit). - Members, Audit log, Create organization and - sending invitations are beta-only. With no active plan, only Settings, Edit - organization and Support are reachable. - Four roles: Owner, Admin, Member, Read only. Only Owners manage billing, - transfer ownership, or create keys with PutObjectRetention/PutObjectLegalHold; - Owners and Admins invite, change roles, remove members, rename the org, and - delete buckets. Roles apply in the console; the S3 API has no users or roles, - and a key is capped at its creator's role. Narrowing a role or removing a - member REVOKES their keys that exceed it. At least one Owner always; transfer - makes you Admin and needs a sign-in within five minutes. The beta gates - SENDING INVITATIONS: single-use links, expire in 14 days, max 25 pending. - Audit log kept 90 days, CSV export up to 20,000 rows. Organization switching - is in the organization menu and per browser tab; leave an organization from - Settings (not as its last Owner). Deleting an organization is not available - in the console yet (support@filone.com) + RELEASED. A "Coming Soon" page with a waitlist form. What works today: + ordinary S3 access keys scoped to a bucket, which is how LangChain, LlamaIndex, + Vercel AI SDK and CrewAI connect +- [App - Organization](https://docs.filone.com/app/organization): Every account + starts as a one-person organization with you as Owner. Members, Billing and + Audit log are in the left sidebar's Organization group; the organization menu + at the top holds Edit organization, your organizations, and Create + organization (any role; up to 10 owned; a new organization has no free trial, + needs a payment method and is billed separately). Four roles: Owner, Admin, + Member, Read only. Only Owners manage billing, transfer ownership, or grant + Set retention / Set legal hold; Owners and Admins invite, change roles, remove + members, rename the org, and delete buckets. Roles apply in the console; the S3 + API has no users or roles, and a key is capped at its creator's role. Narrowing + a role or removing a member REVOKES their keys that exceed it, and they are + emailed which keys. At least one Owner always; transfer makes you Admin and + needs a sign-in within five minutes. Invitations: single-use links, expire in + 14 days, max 25 pending. Audit log kept 90 days, CSV export up to 20,000 rows. + Deleting an organization is not available in the console yet + (support@filone.com) - [App - Billing](https://docs.filone.com/app/billing): Plan card, usage card, - payment method, choosing a plan, invoices, "Need help?" panel. Its own page - at /billing, opened from the organization menu at the top of the sidebar. Visible to - Owners and Admins; every action is Owner-only. A FAILED PAYMENT shows a - "Payment failed" badge and a "Your last payment failed" banner, and makes the - DASHBOARD read-only. Usage card shows Storage and Egress (egress "Free" on - paid) and an "Estimated total" on per-TB plans. Payment method: "No card on - file", card brand and last four, or "Billed by invoice". "Choose your plan": - Pay as you go ($5.99/TB/month, $5.99 minimum) or Business plan (custom - pricing, 1, 3, or 5-year terms). Invoices list shows the - 12 most recent issued invoices, INCLUDING UNPAID (drafts not shown). Card - details live in the Stripe portal, which is also where cancellation happens -- [App - Settings](https://docs.filone.com/app/settings): Profile fields (full name - <= 200 chars; valid email, disposable rejected; the organization's name is not - part of the profile and is edited on the Edit organization page), an - Organizations section to switch or leave organizations, notification preferences (Marketing - emails only; no upload or storage-limit notification setting), pointer to - Account Security. Changing your email RESETS VERIFICATION and re-triggers the - verification-screen redirect; Google/GitHub sign-ins manage name and email at - the provider. The "Danger zone" card covers "Delete account": not available in - the console yet, email support@filone.com -- [App - Support](https://docs.filone.com/app/support): The "Talk to an expert" form, - opened from "Support" in the user menu at the bottom of the sidebar. All fields required, starts empty, four - categories, ~1 business day response. Replies arrive by email; the console does - not show a ticket list. Sales: "Contact sales team" in the "Choose your plan" - dialog, or "Talk to sales" in Billing's "Need help?" panel on trial/no plan -- [FAQ](https://docs.filone.com/faq): Common questions on S3 compatibility, - blockchain/crypto requirements, data residency, deletion behavior, migration - from AWS S3, backups, durability, multiple users (organizations, in beta), - and Filecoin data integrity mechanics -- [Limits & Quotas](https://docs.filone.com/limits): Account limits (storage, - egress, buckets), object size limits (max 5 TB, use multipart above 5 GB), - API rate limits, and bucket/key naming constraints (object keys 1,024 - characters in the dashboard; 1,024 bytes via the API, standard S3 and not - independently confirmed) + payment method, choosing a plan, invoices, "Need help?" panel, opened from the + sidebar's Organization group. Visible to Owners and Admins; every action is + Owner-only. During the trial the status badge reads Active with plan Free + trial; manually billed organizations show Billed manually or Custom plan. A + FAILED PAYMENT makes the console read-only. An Owner can Reactivate a canceled + subscription ("Your data is still here"). "Choose your plan": Pay as you go + ($5.99/TB/month, $5.99 minimum) or Business plan (custom pricing, 1, 3, or + 5-year terms). Invoices list shows the 12 most recent issued invoices, + INCLUDING UNPAID. Card details and cancellation (Owners only) live in the + Stripe portal +- [App - Settings](https://docs.filone.com/app/settings): Profile card with Avatar, + Name (autosaves when you leave the field) and Email (changed through a Change + email dialog; changing it RESETS VERIFICATION); Google/GitHub sign-ins manage + these at the provider. Organizations section to switch or leave + organizations, notification preferences (Marketing emails only), pointer to + Account Security. "Delete account" is not available in the console yet: email + support@filone.com +- [App - Support](https://docs.filone.com/app/support): The Support page, opened + from Support at the bottom of the left sidebar. Category (Product issue, + Billing issue, General inquiry, Feature request) and Message; your name, + organization and email come from your account, and the reply goes to your + account email. Send message; ~1 business day response. Common questions and a + Report a bug link. Sales: "Contact sales team" in the "Choose your plan" dialog, + or "Talk to sales" in Billing's "Need help?" panel on trial/no plan + +## Optional + +- [FAQ](https://docs.filone.com/faq): Common questions on S3 compatibility (needs + the endpoint and path-style addressing), blockchain/crypto requirements, data + residency, deletion behavior, migration from AWS S3, backups, durability (no + published figure; public 99.9% uptime SLA at https://www.filone.com/sla), + multiple users (organizations and roles), and Filecoin data integrity mechanics