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:
- updated delegator metadata (usually
targets) that authorizes new delegated keys; - delegated role metadata signed by the new delegated keys.
Endpoint
POST /tuf/v1/metadata/delegated/rotate?appName=<app_name>
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
Authorization | Bearer <token> |
Auth and Permissions
- Requires a valid JWT in the
Authorizationheader. - Caller must be an admin for the selected app.
appNameis required and determines which TUF repository is updated.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
appName | string | ✅ | Name of the application whose delegated metadata rotation is staged |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
role | string | ✅ | Delegated role name to rotate keys for; must not be a top-level role (root, targets, snapshot, timestamp) |
delegator | string | ❌ | Delegating role name; defaults to targets |
metadata | object | ✅ | Staged metadata payloads for rotation flow |
metadata.targets | object | ⚠️ Conditional | New delegator targets metadata that authorizes new delegated keys (recommended, often required in practice) |
metadata.<role> | object | ⚠️ Conditional | New 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_typeis 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.
delegatormust authorizerolein itsdelegationsblock; 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:
- Prepare updated delegator metadata (
targetsby default) with new delegated keyids indelegations. - Stage delegator metadata (and optionally delegated metadata) via
POST /tuf/v1/metadata/delegated/rotate. - Collect required signatures offline and submit one-by-one through
POST /tuf/v1/metadata/sign?appName=<app_name>. - Repeat sign calls until each staged metadata object reaches threshold.
- Finalize through existing pipeline, which updates snapshot and timestamp consistently.
- Monitor task completion via Check Task using returned
task_id.
Recommended order for safer rotation:
- Stage and sign updated
targetsthat authorizes new delegated keys. - Stage and sign delegated role metadata using those new keys.
Troubleshooting
Unauthorized keyid
- Confirm signer
keyidis 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
delegatoris correct (default istargets). - Verify
delegator.signed.delegations.rolescontains the delegatedrole. - If authorization changed, stage updated delegator metadata first.
Version not monotonic
- Compare with currently trusted delegated/delegator metadata versions.
- Increase
signed.versionso it is strictly greater than trusted. - Do not reuse stale metadata blobs from previous drafts.
Expired metadata
- Ensure
signed.expiresis in the future at request processing time. - Use sufficient validity window to avoid expiry during offline signing delay.