Skip to main content

Stage Delegated Key Rotation Metadata

Stage delegated metadata updates for offline signing during delegated key rotation. This endpoint stores pending metadata in Redis and creates signing task state, then you complete signatures through the existing sign flow.

Use this route when you rotate keys for an existing delegated role and need to safely stage:

  1. updated delegator metadata (usually targets) that authorizes new delegated keys;
  2. delegated role metadata signed by the new delegated keys.

Endpoint

POST /tuf/v1/metadata/delegated/rotate?appName=<app_name>

Headers

HeaderValue
Content-Typeapplication/json
AuthorizationBearer <token>

Auth and Permissions

  • Requires a valid JWT in the Authorization header.
  • Caller must be an admin for the selected app.
  • appName is required and determines which TUF repository is updated.

Query Parameters

ParameterTypeRequiredDescription
appNamestringName of the application whose delegated metadata rotation is staged

Request Body

FieldTypeRequiredDescription
rolestringDelegated role name to rotate keys for; must not be a top-level role (root, targets, snapshot, timestamp)
delegatorstringDelegating role name; defaults to targets
metadataobjectStaged metadata payloads for rotation flow
metadata.targetsobject⚠️ ConditionalNew delegator targets metadata that authorizes new delegated keys (recommended, often required in practice)
metadata.<role>object⚠️ ConditionalNew delegated role metadata for role, signed by the rotated delegated keys (recommended)

At least one of metadata.targets or metadata.<role> must be present.

Example Request

curl --location 'http://localhost:9000/tuf/v1/metadata/delegated/rotate?appName=tuf-admin' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <jwt_token>' \
--data '{
"role": "default",
"delegator": "targets",
"metadata": {
"targets": {
"signatures": [
{
"keyid": "b11cb77f6ab74c7557f3cd2c90a9ef861601f9f1d5484ee8f3f9e1f2dd01aabc",
"sig": "<targets_signature_hex>"
}
],
"signed": {
"_type": "targets",
"version": 8,
"spec_version": "1.0.31",
"expires": "2027-01-15T00:00:00Z",
"targets": {},
"delegations": {
"keys": {
"9bc0...newkey": {
"keytype": "ed25519",
"scheme": "ed25519",
"keyval": { "public": "<delegated_new_public_key_hex>" }
}
},
"roles": [
{
"name": "default",
"keyids": ["9bc0...newkey"],
"threshold": 1,
"paths": ["tuf-admin/nightly/*"]
}
]
}
}
},
"default": {
"signatures": [
{
"keyid": "9bc0...newkey",
"sig": "<delegated_signature_hex>"
}
],
"signed": {
"_type": "targets",
"version": 6,
"spec_version": "1.0.31",
"expires": "2027-01-15T00:00:00Z",
"targets": {}
}
}
}
}'

Validation Rules and Security Notes

The server validates staged delegated rotation metadata before storing it:

  • Bootstrap state must be completed. Pre-bootstrap (pre-*) and signing bootstrap (signing-*) states are rejected.
  • Signed metadata type must be targets. Any other _type is rejected.
  • Expiration must be in the future. Expired metadata cannot be staged.
  • Duplicate signature keyids are rejected. One keyid may appear only once per metadata object.
  • Delegation keyid must match key material. Key IDs are recomputed from key material and must match declared keyids.
  • Version monotonicity is strict. Incoming staged version must be greater than current trusted version.
  • Delegation authorization is required. delegator must authorize role in its delegations block; otherwise staging is rejected.

These checks protect against rollback, freeze, unauthorized delegated signer injection, and malformed signature sets.

Response

Success Response (200 OK)

When validation passes, pending metadata is stored in Redis under keys like {ROLE}_SIGNING_{admin}_{app} and a signing task state is created:

{
"data": {
"task_id": "8d6d0dc1-7e8b-4ad9-a6d8-0f6e857d5f7b",
"last_update": "2026-05-14T16:31:22.512345Z"
},
"message": "Metadata rotation staged for signing"
}

Step-by-Step Flow with /metadata/sign

Use this safe sequence for delegated key rotation:

  1. Prepare updated delegator metadata (targets by default) with new delegated keyids in delegations.
  2. Stage delegator metadata (and optionally delegated metadata) via POST /tuf/v1/metadata/delegated/rotate.
  3. Collect required signatures offline and submit one-by-one through POST /tuf/v1/metadata/sign?appName=<app_name>.
  4. Repeat sign calls until each staged metadata object reaches threshold.
  5. Finalize through existing pipeline, which updates snapshot and timestamp consistently.
  6. Monitor task completion via Check Task using returned task_id.

Recommended order for safer rotation:

  1. Stage and sign updated targets that authorizes new delegated keys.
  2. Stage and sign delegated role metadata using those new keys.

Troubleshooting

Unauthorized keyid

  • Confirm signer keyid is listed in the role's authorized keyids.
  • Recompute keyid from key material and verify exact match.
  • Ensure signatures are produced from the correct private key for that keyid.

No delegation found

  • Check that delegator is correct (default is targets).
  • Verify delegator.signed.delegations.roles contains the delegated role.
  • If authorization changed, stage updated delegator metadata first.

Version not monotonic

  • Compare with currently trusted delegated/delegator metadata versions.
  • Increase signed.version so it is strictly greater than trusted.
  • Do not reuse stale metadata blobs from previous drafts.

Expired metadata

  • Ensure signed.expires is in the future at request processing time.
  • Use sufficient validity window to avoid expiry during offline signing delay.