Skip to content

feat(app): extend the live grant instead of replacing it - #87

Merged
volod-vana merged 4 commits into
mainfrom
volod/request-remove-scopes
Oct 8, 2026
Merged

volod-vana merged 4 commits into
mainfrom
volod/request-remove-scopes

Conversation

@volod-vana

@volod-vana volod-vana commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Why

The gateway keeps one grant per (owner, app). An approval replaces that grant's scopes, so vana app request --scopes whoop.recovery from an app that already holds oura.sleep would leave it with whoop.recovery alone. Apps have been rebuilding the union by hand.

What

vana app request:

  • Finds the owner from an earlier approval of this app key on this machine (the stored grant id; grant ids are one per owner and app), reads that owner's live grant at the gateway, and sends the union of its still-granted scopes and --scopes.
  • Prints what it keeps, adds and removes before creating the request (stderr, human mode).
  • --remove-scopes a,b: live entries to give up. Matched verbatim. A scope both requested and removed is exit 2.
  • --owner <address>: whose grant to extend. Needed when two different people approved this app from this machine; the CLI never guesses between them (owner_ambiguous), because merging one person's scopes would ask the other for data they never granted.
  • --no-merge-grant: send --scopes verbatim.
  • --json outcomes (approved, pending under --no-input, denied, timed out) carry kept, added, removed and grantUnion (status: merged, no_live_grant, owner_unknown, owner_ambiguous, disabled, unavailable; plus owner, grantId, reason, notCarried).
  • A gateway that does not answer within 5s never blocks the request: it goes out with --scopes and status: "unavailable".
  • A live raw read of a question's source is not carried (the service rejects a source that is also a read scope on the same request); it is listed under notCarried. vana app ask goes through the same path.
  • The stored request records the merged scopes and removeScopes, so vana app requests show checks the replaced-grant state against what was actually asked.

Also, from a separate report: vana login always printed "Credentials saved to ~/.vana/auth.json". It now prints the real file (getAuthFilePath(), home-shortened), which follows VANA_HOME and the Account environment (for example auth.account-dev.vana.org.json).

SDK dependency

Bumps @opendatalabs/vana-sdk 4.0.0 to 4.3.1 (exact pin, which the SEA build carries through). The merge now comes from the SDK (mergeWithLiveGrant / unionGrantScopes); src/core/grant-union.ts is a re-export plus the conflict check worded for the CLI flags. removeScopes goes on the DCR body as a typed field. A malformed --remove-scopes entry is exit 2 before any call.

4.3.1 rather than 4.3.0: 4.2.0 and 4.3.0 shipped dist/protocol/jobs-client.js with an extensionless ../config/contracts.config import that Node's ESM loader cannot resolve (fixed in vana-sdk#216).

Between 4.0.0 and 4.3.1 the jobs client started signing a quoted price on its own when the gateway answers 402. The enclave leg of vana app read now passes maxPrice: "0", so a charged enclave read stops before anything is signed and exits 4 as payment_required instead of spending without --pay. The other SDK changes in that range (mainnet enclave trust anchors, JobTransportError.details) need nothing here.

Tests

test/cli/app-request.test.ts: merge with removal, the printed plan, no earlier approval (no gateway call), two approvers (no gateway call), --owner, --no-merge-grant, gateway down, requested-and-removed conflict, question source not carried, bad --owner. test/cli/auth.test.ts: the saved-credentials line for production, dev Account, and VANA_HOME. All gateway and controller calls are fakes.

test/cli/app-read-loop.test.ts: enclave read sends maxPrice: "0" and maps a refused quote to exit 4. pnpm validate green (772 tests), run with temp HOME and VANA_HOME.

Release

feat commit, so semantic-release cuts 0.40.0. The default changes: a repeat request from the same app key now asks for the union instead of replacing.

https://claude.ai/code/session_01Fcv6uEy4zcXaigzDNxeW3j

Login always printed "Credentials saved to ~/.vana/auth.json", even when
VANA_HOME moved the file or a non-production Account gave it its own
name (auth.account-dev.vana.org.json). It now prints getAuthFilePath(),
home-shortened.

Claude-Session: https://claude.ai/code/session_01Fcv6uEy4zcXaigzDNxeW3j
The gateway keeps one grant per owner and app, and an approval replaces
its scopes. `vana app request` now reads the app's live grant when this
machine already holds an approval for the app key (or with --owner) and
asks for the union, printing what it keeps, adds and removes first.
--remove-scopes gives entries up, --no-merge-grant sends --scopes
verbatim. Two different earlier approvers are never guessed between.
The --json outcome carries kept, added, removed and grantUnion.

The merge is a local copy of the SDK's mergeWithLiveGrant (vana-sdk#215,
unreleased); removeScopes reaches the approval page once the SDK pin is
bumped to the release that sends it.

Claude-Session: https://claude.ai/code/session_01Fcv6uEy4zcXaigzDNxeW3j
Bump @opendatalabs/vana-sdk to 4.3.1, which ships mergeWithLiveGrant and
removeScopes on createAccessRequest. The local copy of the merge becomes
a re-export plus the flag-worded conflict check, removeScopes goes on the
request body as a typed field, and a malformed --remove-scopes entry is
refused as bad usage before any call.

Claude-Session: https://claude.ai/code/session_01Fcv6uEy4zcXaigzDNxeW3j
Since vana-sdk 4.2.0 the jobs client signs a quoted price on its own
when the gateway answers 402. Pass maxPrice "0" so a charged enclave
read stops before anything is signed and exits 4 as payment_required,
as the CLI promised before the bump.

Claude-Session: https://claude.ai/code/session_01Fcv6uEy4zcXaigzDNxeW3j
@volod-vana
volod-vana merged commit 545af5c into main Oct 8, 2026
7 checks passed
github-actions Bot pushed a commit that referenced this pull request Oct 8, 2026
## [0.40.0](v0.39.0...v0.40.0) (2026-10-08)

### Features

* **app:** extend the live grant instead of replacing it ([#87](#87)) ([545af5c](545af5c)), closes [vana-sdk#215](vana-com/vana-sdk#215)

### Bug Fixes

* **server:** run personal server 1.31.0 ([#88](#88)) ([34f8fe1](34f8fe1))
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.40.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant