Skip to content

[Pruning] Added a design doc for tlog-tiles pruning#935

Open
mhutchinson wants to merge 2 commits intotransparency-dev:mainfrom
mhutchinson:prune
Open

[Pruning] Added a design doc for tlog-tiles pruning#935
mhutchinson wants to merge 2 commits intotransparency-dev:mainfrom
mhutchinson:prune

Conversation

@mhutchinson
Copy link
Copy Markdown
Contributor

This is a design for #855. If accepted, we can move on to implementation.

This is a design for transparency-dev#855. If accepted, we can move on to implementation.
@mhutchinson mhutchinson requested a review from a team as a code owner April 15, 2026 09:58
Comment thread docs/design/pruning.md
Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md

## Spec Requirements & Ambiguities

The [tlog-tiles] spec (revision `1cd32db`) defines the rules for pruning but leaves operational details as an exercise for the implementation:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md
* **Ordering**: To maintain consistency with Tessera's existing Garbage Collection mechanism (which cleans up obsolete partial tiles), the tool should process resources in a bottom-up, left-to-right order: first entry bundles, then Level 0 tiles, and finally higher-level tiles. Within each resource type, it should proceed from the lowest index to the highest.

### 4. Safety Features
* **Confirmation Prompt**: The tool scans the range to be pruned and prompts the operator with the count of files (tiles and entry bundles) to be moved before proceeding.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to actually list the objects in order to count them, or would it suffice to just calculate the lower bound on the number of resources given the range?

Personally, I think that knowing there are x thousand logical tile/bundle addresses to be moved is more useful than xxx thousand partial and full revisions of some unknown number of logical addresses to be moved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't much mind TBH. I guess scanning the range is expensive so this needs to be reconsidered. Leaving this comment open.

Comment thread docs/design/pruning.md

### 4. Safety Features
* **Confirmation Prompt**: The tool scans the range to be pruned and prompts the operator with the count of files (tiles and entry bundles) to be moved before proceeding.
* **Undo Command**: The tool provides an `undo` command that moves files back from the archive to the active area and restores the `min_index` file to its previous value (by storing the previous value in the archive during pruning), facilitating recovery from operator error. In the event of manual recovery, the operator can manually update the `min_index` file based on the data they have restored.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this interact with GC?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The undo feature? I had assumed that by the time one prunes a tree, it would be thoroughly GCd. Is it a supported configuration to have a no-GC deployment though?

Comment thread docs/design/pruning.md
### Archive-in-Place (Renaming Files)
We considered keeping archived files in the same storage location (bucket or directory) but renaming them (e.g., appending `~` or moving to a sub-folder like `archive/` within the same bucket).

* **Why it was not picked**: While this makes the "move" operation fast and atomic (metadata rename), it creates security risks for cloud storage users. If a GCS bucket is served publicly with uniform bucket-level access, everything in that bucket is public. Hiding an `archive/` folder or renamed files would require complex IAM conditions or putting a proxy/load balancer in front of the bucket. This violates Tessera's goal of zero-infrastructure read paths. Moving to a separate private bucket provides a much stronger security boundary with less operational complexity.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also just accept that motivated folks would still be able to access archived resources via the (unspecified) archive path?

I'm not sure I understand why a strong security boundary for archived resources is important.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a strong security boundary. It's:
a) avoiding polluting the serving namespace, e.g. your comment about the min_index file
b) a minor concern about any edge caches also caching this stuff if requested.

If we're strongly opinionated that putting this stuff on the public paths is cool, we can consider changing the primary suggestion for these alternatives.

Comment thread docs/design/pruning.md Outdated
We considered relying on cloud-specific features like GCS Object Versioning or Soft Delete. Under this model, the tool would simply delete the files from the public bucket. If Object Versioning is enabled, the deleted files would become noncurrent versions (returning `404` to public requests) and could be restored later.

* **Why it was not picked**:
* **Cost Inefficiency**: Tessera frequently updates partial tiles and entry bundles during normal operation. If Object Versioning were enabled on the bucket, every such update would create a new billable version, leading to uncontrolled storage cost growth unless complex lifecycle rules were configured to clean them up. Furthermore, if versioning is enabled, Tessera's existing Garbage Collection mechanism (which deletes obsolete partial tiles) becomes ineffective at saving quota, as the deleted files are merely retained as noncurrent versions.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not arguing that object versioning is the right approach at all, but the assertion here about Tessera frequently updating partial tiles and entry bundles is... not true?

Tessera only ever re-writes a tile/entrybundle resource if there was an unrecoverable error during integration, which is relatively rare compared to the number of resources written overall.

And GC could, of course, just explicitly delete the object plus all of its (almost certainly 1) versions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good catch. Updating is the wrong term. This was going in a few different directions and ended up botched. Tried to clarify what was intended: object versioning is not recommended because GC cleans up a lot of stuff. We don't want to start recommending object versioning for this feature, if that then makes GC harder.

Comment thread docs/design/pruning.md Outdated
* **Cost Inefficiency**: Tessera frequently updates partial tiles and entry bundles during normal operation. If Object Versioning were enabled on the bucket, every such update would create a new billable version, leading to uncontrolled storage cost growth unless complex lifecycle rules were configured to clean them up. Furthermore, if versioning is enabled, Tessera's existing Garbage Collection mechanism (which deletes obsolete partial tiles) becomes ineffective at saving quota, as the deleted files are merely retained as noncurrent versions.
* **Portability**: This approach relies on specific cloud provider features that do not translate well to simple POSIX filesystems or other cloud providers with different versioning semantics. The "move to archive" approach is universally applicable across all storage drivers supported by Tessera.

* **Note**: While we rejected Object Versioning for the reasons above, a variant relying solely on **Soft Delete** (without versioning enabled) is considered as a viable option for GCS deployments (see the **GCS "Brave Mode" Alternative** in the Archiving Strategy section).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems inconsistent with the opening para in this section, would it make sense to remove Soft Delete entirely here and just leave this dismissal for Object Versioning?

Copy link
Copy Markdown
Contributor Author

@mhutchinson mhutchinson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comments. Addressed many of them.

Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md Outdated
Comment thread docs/design/pruning.md Outdated

The tool performs the following steps:
1. **Validation**: Ensures the target index $N$ is less than the current checkpoint size, greater than or equal to the current `min_index`, and enforces that $N$ is a multiple of 256 (to align with tile boundaries).
2. **State Commitment**: Writes the new $N$ to a statically served `min_index` file at the root of the log.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my initial thought, but the spec explicitly has this TODO:

TODO: Some HTTP endpoint for fetching the minimum index? The semantics would be something like: serving a minimum index equivalent to returning 404 from the tiles that would be deleted by the pruning criteria, including when evaluating a log client's availability policies.

If logs are going to do pruning, it seems like a good idea that they at least advertise what they believe they are running with. Even if this isn't cryptographically committed to. Really we need the spec to clarify this, and so I proposed this as a forcing function.

Comment thread docs/design/pruning.md
* **Ordering**: To maintain consistency with Tessera's existing Garbage Collection mechanism (which cleans up obsolete partial tiles), the tool should process resources in a bottom-up, left-to-right order: first entry bundles, then Level 0 tiles, and finally higher-level tiles. Within each resource type, it should proceed from the lowest index to the highest.

### 4. Safety Features
* **Confirmation Prompt**: The tool scans the range to be pruned and prompts the operator with the count of files (tiles and entry bundles) to be moved before proceeding.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't much mind TBH. I guess scanning the range is expensive so this needs to be reconsidered. Leaving this comment open.

Comment thread docs/design/pruning.md

### 4. Safety Features
* **Confirmation Prompt**: The tool scans the range to be pruned and prompts the operator with the count of files (tiles and entry bundles) to be moved before proceeding.
* **Undo Command**: The tool provides an `undo` command that moves files back from the archive to the active area and restores the `min_index` file to its previous value (by storing the previous value in the archive during pruning), facilitating recovery from operator error. In the event of manual recovery, the operator can manually update the `min_index` file based on the data they have restored.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The undo feature? I had assumed that by the time one prunes a tree, it would be thoroughly GCd. Is it a supported configuration to have a no-GC deployment though?

Comment thread docs/design/pruning.md
### Archive-in-Place (Renaming Files)
We considered keeping archived files in the same storage location (bucket or directory) but renaming them (e.g., appending `~` or moving to a sub-folder like `archive/` within the same bucket).

* **Why it was not picked**: While this makes the "move" operation fast and atomic (metadata rename), it creates security risks for cloud storage users. If a GCS bucket is served publicly with uniform bucket-level access, everything in that bucket is public. Hiding an `archive/` folder or renamed files would require complex IAM conditions or putting a proxy/load balancer in front of the bucket. This violates Tessera's goal of zero-infrastructure read paths. Moving to a separate private bucket provides a much stronger security boundary with less operational complexity.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a strong security boundary. It's:
a) avoiding polluting the serving namespace, e.g. your comment about the min_index file
b) a minor concern about any edge caches also caching this stuff if requested.

If we're strongly opinionated that putting this stuff on the public paths is cool, we can consider changing the primary suggestion for these alternatives.

Comment thread docs/design/pruning.md Outdated
We considered relying on cloud-specific features like GCS Object Versioning or Soft Delete. Under this model, the tool would simply delete the files from the public bucket. If Object Versioning is enabled, the deleted files would become noncurrent versions (returning `404` to public requests) and could be restored later.

* **Why it was not picked**:
* **Cost Inefficiency**: Tessera frequently updates partial tiles and entry bundles during normal operation. If Object Versioning were enabled on the bucket, every such update would create a new billable version, leading to uncontrolled storage cost growth unless complex lifecycle rules were configured to clean them up. Furthermore, if versioning is enabled, Tessera's existing Garbage Collection mechanism (which deletes obsolete partial tiles) becomes ineffective at saving quota, as the deleted files are merely retained as noncurrent versions.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good catch. Updating is the wrong term. This was going in a few different directions and ended up botched. Tried to clarify what was intended: object versioning is not recommended because GC cleans up a lot of stuff. We don't want to start recommending object versioning for this feature, if that then makes GC harder.

Comment thread docs/design/pruning.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants