parser_http_server. It serves the same Turnkey HTTP+JSON envelope as the hosted service. Each successful response carries a bootProof with a real NSM attestation document, so any client can verify the response without trusting you, Turnkey’s API, or the network in between.
parser_http_server reads the manifest and ephemeral key that QOS provisions (/qos.manifest, /qos.ephemeral.key), so it runs as a QOS pivot. It does not run on a bare Nitro Enclave without QOS.Prerequisites
- A Turnkey organization, with the
tvcCLI logged in (tvc login). - An operator key held locally (
~/.config/turnkey/orgs/<org-alias>/operator.json, where<org-alias>is the org nametvc loginsaved). That key is what approves your deployments. - Docker, to pull the image and hash the binary inside it.
tvc-deployfrom this repo. It isn’t installed on yourPATH: wherever this page runstvc-deploy, runcargo run --manifest-path tools/tvc-deploy/Cargo.toml --from a checkout of this repo instead.- visualsign-turnkeyclient, to verify the deployment.
- A Turnkey API key for visualsign-turnkeyclient, stored as
~/.config/turnkey/keys/<api-key-name>.publicand<api-key-name>.private(the Turnkey CLI’s key format).tvc logindoesn’t create these files, and visualsign-turnkeyclient refuses to run without them, even when your parse routes are open. Your organization ID is theidunder your org in~/.config/turnkey/tvc.config.toml.
1. Pick and pin the image
Images are published toghcr.io/anchorageoss/parser_http_server. Always reference one by tag and digest: a tag alone is mutable, and a bare digest is shown back as :latest.
2. Create the app
Generate a template withtvc app init -o app.json and set name and manifestSetParams. Make sure the manifest set contains only operators whose keys you hold. If it doesn’t, nobody can approve a deployment and the app is stranded.
The template’s newOperators already holds the public key of your local operator.json, so for a first app you can keep it. To reuse an existing operator instead, list it by ID and clear newOperators:
dangerousEnableDebugModeDeployments false. Debug mode zeroes the PCRs, so an attesting parser can never go healthy in it.
--no-operator-reuse stops tvc from substituting the operator from your last app create (without it, tvc prints Reusing operator ... and uses that one). Check that the printed Manifest Set Operator IDs are the ones you expect. That ID is the <your-operator-id> you pass to deploy-pivot below, and App ID is the <app-id>.
3. Deploy
deploy-pivot re-derives the binary digest from the image and refuses to continue on a mismatch. It then creates the deployment, approves it with your operator key, waits until it’s healthy, and sets it live. Everything after -- becomes the deployment’s pivotArgs, and those are part of the manifest the attestation commits to:
TVC has no environment-variable injection:
pivotArgs is the parser’s entire configuration, and anyone verifying the deployment can read it from the attested manifest.
With --boot-proof-source nsm, GET /health returns 503 until the parser holds a verified, unexpired attestation. A replica whose NSM attestation fails never goes healthy, so “healthy” means each replica has attested successfully.
deploy-pivot approves with tvc deploy approve --dangerous-skip-interactive, so it doesn’t show you the manifest before signing. Step 4 is where you check what you approved.
The app is served at https://<publicDomain>, where publicDomain comes from tvc app list --message-format json. For new apps it’s app-<app-id>.app.turnkey.cloud, but older apps use app-<app-id>.turnkey.cloud, so read it rather than constructing it. The routes are GET /health, POST /visualsign/api/v1/parse and POST /visualsign/api/v2/parse. The parse routes take the Turnkey JSON envelope, not the gRPC messages in the API reference:
curl response proves nothing on its own; verify it as described in the next step.
4. Verify the deployment end to end
visualsign-turnkeyclient checks everything a wallet should check, in one command. Pin the PCRs (see Expected values below), and save the manifest so you can inspect it:--key-name stamps the request. The parser only checks the stamp if you set --allowed-stamp-pubkeys-hex, in which case the key must be on the list; the client needs the key files either way.
A pass means all of the following held:
inputPayloadDigestis the SHA-256 of the payload you sent, and the response’s signed message is the hash of exactly thesignablePayload,inputPayloadDigestandmetadataDigestit returned, so the payload can’t be swapped in transit.- The attestation document (
bootProof.awsAttestationDocB64) verifies against the AWS Nitro root CA, and PCR0-3 match your pinned values. - The attestation’s
public_keyis the key that signed the response. - The manifest from
bootProofhashes to the attestation’suser_data. If a response carries no manifest at all,verifyskips this check, which is why later runs should pin--qos-manifest-hex. - The response signature verifies.
- Pivot Config / Binary Hash equals the
$PIVOT_DIGESTyou computed in step 1. This ties the attestation to the exact binary. - Args are exactly the
pivotArgsyou deployed. - DebugMode is
false. - Manifest Set lists only your operators. The human-readable output shows only the threshold and member count, so add
--jsonand compare eachmanifest.manifestSet.members[].pubKeywith thepublic_keyin youroperator.json. - Hashes / Manifest is the manifest hash. Record it: later runs can pin it with
verify --qos-manifest-hex <hash>, which fails on any change to the deployment.
verify’s JSON output for the binary check: its pivotBinaryHash field holds the manifest hash (user_data), not the binary’s sha256. For the same reason, verify --pivot-binary-hash-hex is compared with user_data, so passing it your $PIVOT_DIGEST fails.
Expected values
For how each check works and how to implement them in your own verifier, see Attestation Verification.
Updating
Everydeploy-pivot creates a new deployment with a new manifest, so the manifest hash changes. The binary hash and PCRs change only if you change the image or TVC changes the QOS runtime. Re-run step 4 after each deploy and update the values you pin.
Next steps
- Attestation Verification — What each check proves, and how to implement it
- Security Model — The TEE threat model
- API Reference — Request and response formats