Conversation
Introduce a self-contained storage model for The Update Framework (TUF)
using the Foundries.io/ota-tuf metadata format.
- Define TUF metadata structs internally (no external TUF type imports):
root, targets, snapshot and timestamp metadata plus AtsKey/Signature.
- Add TufFsHandle under <datadir>/tuf with:
- InitTuf(): generate ed25519 keys for the root, targets, snapshot and
timestamp roles, store them AES-256-GCM encrypted under a key derived
from the HMAC secret, and create a signed initial root.json (20y).
- LoadTuf(): decrypt and load role keys; errors if not initialized.
- GetRoots(): return all root.json files ordered by version.
- Default expirations: root 20y, timestamp 7d, targets/snapshot 90d.
- Use go-securesystemslib/cjson for canonical JSON signing.
Co-authored-by: GitHub Copilot:claude-4-opus <noreply@github.com>
Signed-off-by: Andy Doan <doanac@qti.qualcomm.com>
This was referenced Jun 26, 2026
Member
Author
Add a tuf-init server subcommand to initialize TUF keys and root metadata, and require TUF to be initialized before the server starts. Co-authored-by: GitHub Copilot:claude-4-opus <noreply@github.com> Signed-off-by: Andy Doan <doanac@qti.qualcomm.com>
Add /v1/tuf/root.json (latest) and /v1/tuf/<n>.root.json (specific version) endpoints backed by a new ReadRoot storage method. Co-authored-by: GitHub Copilot:claude-4-opus <noreply@github.com> Signed-off-by: Andy Doan <doanac@qti.qualcomm.com>
This introduces a new API to properly add target to a given tag/update and sign its TUF metadata. Target metadata logic works by: * Finding the latest targets TUF version and application version for a tag. We must know these values to ensure we are creating metadata a device will pull down (if the version isn't higher - it won't pull it). * Increment the TUF version by 10. This gives us some flexibility to resign a Targets meta in the event we need to use it longer than the default 90 day expiration. * Create Snapshot metadata that's basically the same as the Targets. Our configuration/usage allows for these files to follow each other's versions. * Create Timestamp metadata. This follows some clever logic in our current ota-lite backend for setting a version that will work across mulitple updates for a given update tag. Targets/Snapshot get a 90 day expiry. Timestamp get a 7 day expiry. Co-authored-by: GitHub Copilot:claude-4-opus <noreply@github.com> Signed-off-by: Andy Doan <doanac@qti.qualcomm.com>
This introduces an new API that allows us to refresh timestamp metadata for any updates that may need it. When the update expiry is within one day of expiration, it will bump the expiration by a week and resign the metatdata. Signed-off-by: Andy Doan <doanac@qti.qualcomm.com>
We will use this to help populate default data into a TUF target during an Update upload Signed-off-by: Andy Doan <doanac@qti.qualcomm.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This feature probes the update content itself to help automatically generate the TUF Target for the user removing the need for them to have TUF set up outside of this project. Signed-off-by: Andy Doan <doanac@qti.qualcomm.com> Co-authored-by: GitHub Copilot:claude-4-opus <noreply@github.com>
Add --version, --name, --ostree-hash, and --apps flags to the update upload command so users can override the auto-generated TUF target metadata via the new query parameters on the updates create API. Signed-off-by: Andy Doan <doanac@qti.qualcomm.com> Co-authored-by: GitHub Copilot:claude-opus-4.8 <noreply@github.com>
Add a collapsible "Advanced options" section to the update upload form with version, target name, ostree hash, and apps fields. These map to the new query parameters on the updates create API to override the auto-generated TUF target metadata. Signed-off-by: Andy Doan <doanac@qti.qualcomm.com> Co-authored-by: GitHub Copilot:claude-opus-4.8 <noreply@github.com>
It makes more sense to show in the order timestamp,snapshot,target Signed-off-by: Andy Doan <doanac@qti.qualcomm.com>
Collect the de-duplicated set of hardwareIds and tags from across all targets in targets.json and display them in their own fieldsets on the update details page. Signed-off-by: Andy Doan <doanac@qti.qualcomm.com> Co-authored-by: GitHub Copilot:claude-opus-4.8 <noreply@github.com>
Add an isExpired template helper and wrap expired root, timestamp, snapshot, and targets expiration values in a <del> element on the update details page. Signed-off-by: Andy Doan <doanac@qti.qualcomm.com> Co-authored-by: GitHub Copilot:claude-opus-4.8 <noreply@github.com>
Signed-off-by: Andy Doan <doanac@qti.qualcomm.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



This is a fairly substantial change that introduces the ability to transparently manage TUF metadata for Updates. The branch produces a fully functioning server with TUF metadata that aklite will consume. There are some features that will be added once this has been merged:
The current logic for handling timestamp and targets metadata may not jive well with users wanting to move devices between tags. Given the size and scope of this current change, I'd like to delay work on that until I can get this work merged.
I also haven't tested rollback support. The current approach creates a single Target in the targets.json and doesn't not include any other older Targets. I believe aklite will work correctly but this will need to be tested.
This has been reviewed by Claude Sonnet and Claude Opus.