avvy-worker processes long-running 3D model jobs out of the request path and POSTs results back to state-server. Each callback is CBOR-encoded, HMAC-SHA256-signed, and bound to one of four task families.
| Task type | Produces | Callback signature header |
|---|---|---|
model.preview.v1 |
previews + metadata | X-Model-Preview-Signature |
model.object_pipeline.v1 |
previews + metadata + processed CBOR + canonical model artifact set | X-Model-Object-Signature |
model.projection.step.v1 |
source / preprocessed / generated image + attempts/scores | X-Model-Projection-Signature |
model.projection.model.v1 |
generated 3D model artifacts + previews | X-Model-Projection-Model-Signature |
The header is sha256=<hex-hmac>. The HMAC is computed over the raw body bytes (not a canonicalised form) with the shared callback_secret.
POST <callback_url>
Content-Type: application/cbor
X-Model-<Family>-Signature: sha256=<hex(HMAC-SHA256(raw_body, callback_secret))>
<raw CBOR body>
callback_url is provided in the asynq task payload. There is no environment-variable fallback — the URL must be in the payload.
expected = "sha256=" + hex(HMAC_SHA256(body, callback_secret)).X-Model-<Family>-Signature header.The server must use a constant-time comparison to avoid timing attacks.
| Field | Type | Notes |
|---|---|---|
model_hash |
string | Required. |
task_id |
string | Optional. |
status |
string | completed | failed. |
error |
string | Truncated error message (when failed). |
metadata.title |
map[string]string | Language → title. |
metadata.description |
map[string]string | Language → description. |
metadata.tags |
[]string | |
metadata.estimated_dimensions |
[3]float64 | [width, height, depth]. |
metadata.estimated_scale_factor |
float64 | |
metadata.restricted_detected[].category_id |
string | |
metadata.restricted_detected[].confidence |
float64 | |
metadata.restricted_detected[].evidence |
string | |
previews[].angle_deg |
float64 | |
previews[].mime |
string | |
previews[].width / previews[].height |
int | |
previews[].image_data |
bytes | CBOR byte string. |
processed_cbor.{kind, logical_name, content_type, sha256, bytes} |
mixed | Public view.cbor artifact. |
canonical_model.{kind, logical_name, content_type, sha256, bytes} |
mixed | Internal canonical GLB. |
artifacts[] |
object | Auxiliary meshes / textures / materials. |
manifest |
object | Prebuilt asset manifest. |
For model.object_pipeline.v1: processed_cbor is the public artifact eventually exposed as processed_cbor_uri; canonical_model is the internal canonical GLB used by state-server to persist and validate pipeline outputs.
For model.projection.step.v1 the payload additionally includes job_id, step_id, sequence, prompt_original, prompt_used, three image stages (source_image, preprocessed_image, generated_image with {mime, data, sha256}), and an attempts[] log carrying attempt_id, generation_prompt, scores, flaws, and accepted.
Callback POSTs may be retried by asynq if the HTTP call fails (network, TLS, 5xx). State-server handlers MUST treat every callback as potentially-redelivered:
(task_type, model_hash, task_id) and ignore duplicates.2xx only after the result is durably persisted.callback_secret as a shared secret; state-server and worker must be updated together.callback_url and a valid TLS trust chain.callback_url — keep Redis on a private network and restrict worker egress where possible.gitlab.avvyland.com/avvy/avvy-worker — README.md. gitlab.avvyland.com/avvy/state-server — docs/openapi-v2.yml (internal callback endpoints under Model Preview / Model Objects).