Skip to content

feat(scripts): private key to a vehicle-scoped permission JWT in one command - #21

Open
elffjs wants to merge 1 commit into
mainfrom
tooling/vehicle-token-script
Open

feat(scripts): private key to a vehicle-scoped permission JWT in one command#21
elffjs wants to merge 1 commit into
mainfrom
tooling/vehicle-token-script

Conversation

@elffjs

@elffjs elffjs commented Jul 29, 2026

Copy link
Copy Markdown
Member

signin.sh stops at the /siwe sign-in token, which no data API accepts. Getting a token dq will actually take means four curls and a hand-run cast wallet sign every time.

That friction has a real cost: the GCP node went weeks with no cloudevent or range traffic, so several per-op dashboards had never rendered a single sample — not because the instrumentation was broken, but because nobody could conveniently issue the queries.

Usage

The JWT is the only thing on stdout, so it composes:

TOKEN=$(PK=0x… TOKEN_ID=192641 scripts/vehicle-token.sh)
curl -H "authorization: Bearer $TOKEN" https://dq.gcp.dimo.xyz/query \
  -H 'content-type: application/json' \
  -d '{"query":"query{availableCloudEventTypes(subject:\"did:erc721:137:0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF:192641\"){type count firstSeen lastSeen}}"}'

Progress and errors go to stderr. -v also dumps the decoded claims there — that's how you check what the chain actually granted, since the exchange returns a token carrying only the permissions your license holds. Asking for more than you have is not an error and would otherwise fail confusingly later.

Defaults target dauth.gcp.dimo.xyz and the Polygon vehicle NFT; BASE_URL, NFT_CONTRACT, PRIVILEGES and AUDIENCE all override.

Notes

  • Uses the deprecated-but-still-served tokenId/privileges fields rather than the newer asset-DID + named-permissions shape, so it doesn't depend on which dauth is deployed.
  • Requires cast (Foundry), curl, jq — same as signin.sh.

Validation

Run end to end against dauth.gcp.dimo.xyz: challenge, personal_sign, and /siwe/token all succeed with a throwaway key; /exchange correctly returns 403 because that key holds no permissions on the vehicle. Guard paths (missing PK, missing TOKEN_ID, non-numeric PRIVILEGES) checked too.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PUy3eg2C7hDBPBNLyLRgkj

…command

signin.sh stops at the /siwe sign-in token, which no data API accepts. Getting a
token dq will actually take meant four curls and a hand-run `cast wallet sign`
every time, which is enough friction that people avoid issuing test queries at
all — the GCP node went weeks with no cloudevent or range traffic, so several
per-op dashboards had never rendered a single sample.

vehicle-token.sh carries on through /exchange/tokens/exchange to the permission
token. The JWT is the only thing on stdout, so it composes:

    TOKEN=$(PK=0x… TOKEN_ID=192641 scripts/vehicle-token.sh)
    curl -H "authorization: Bearer $TOKEN" https://dq.gcp.dimo.xyz/query …

Progress and errors go to stderr; -v also dumps the decoded claims there, which
is how you check what the chain actually granted — the exchange returns a token
carrying only the permissions the license holds, so asking for more than you
have is not an error and would otherwise fail confusingly later.

Uses the deprecated-but-served tokenId/privileges fields rather than the newer
asset-DID + named-permissions shape, so it does not depend on which dauth is
deployed.

Validated end to end against dauth.gcp.dimo.xyz: challenge, personal_sign and
/siwe/token all succeed with a throwaway key, and /exchange correctly 403s
because that key holds no permissions on the vehicle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PUy3eg2C7hDBPBNLyLRgkj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant