G

Capability Tokens

Capability Tokens

Every cross-layer action on Gao Internet requires a capability token — a time-bound, domain-scoped permission that the Capability Token Engine validates before forwarding your call to the target layer.

This is the core security mechanism. No capability = no action.

Concept#

Your dApp calls sdk.settlement.createIntent(...)
  ↓ SDK checks: do you have "settlement:intent:create" capability?
  ↓ yes                    ↓ no
  Forward to L4 →          throw GAO-4001

Token Format#

<layer>:<resource>:<action>

Examples:

intelligence:agent:run
intelligence:agent:deploy
intelligence:sandbox:execute
settlement:intent:create
identity:record:resolve
infrastructure:storage:write
infrastructure:compute:allocate
transport:message:send
developer:connector:gmail:send
developer:connector:slack:send
developer:connector:meshii:message
developer:connector:payii:intent

Request a Token#

const cap = await sdk.developer.capability.request(
  'intelligence:agent:run',   // capability string
  'myapp.gao',                // domain scope (usually your app domain)
  3600                        // TTL in seconds (default 3600 = 1 hour)
)

// cap.token   — attach to SDK calls
// cap.hash    — for audit lookups
// cap.expires_at — unix timestamp

How to Use#

The SDK auto-attaches tokens when you call methods that require them — as long as you've requested the token first in the current session.

For explicit attachment (payment, high-risk ops):

const cap = await sdk.developer.capability.request('settlement:intent:create', 'myapp.gao')

const intent = await sdk.settlement.createIntent({
  amount: '25.00',
  currency: 'USDC',
  recipient: 'merchant.gao',
  idempotency_key: crypto.randomUUID(),
  capability: cap.token,        // explicit attachment required for payments
})

Token Lifecycle#

request() → issued (stored in Redis, TTL)
    ↓
validate on each SDK call
    ↓
expires after TTL → GAO-4001 error
    ↓
request() again

Tokens are one-time for sensitive ops (payments, deploys) and reusable for read operations within TTL.


Handle Expiry#

import { GaoError } from '@gao/system-sdk'

async function runWithCapability(fn: (cap: CapabilityToken) => Promise<void>) {
  let cap = await sdk.developer.capability.request('intelligence:agent:run', 'myapp.gao')

  try {
    await fn(cap)
  } catch (err) {
    if (err instanceof GaoError && err.code === 'GAO-4001') {
      // Token expired — refresh and retry once
      cap = await sdk.developer.capability.request('intelligence:agent:run', 'myapp.gao')
      await fn(cap)
    } else {
      throw err
    }
  }
}

Validate a Token#

const result = await sdk.developer.capability.validate(cap.token)
// result.valid       — boolean
// result.domain      — token's domain scope
// result.capability  — capability string
// result.expires_at  — expiry timestamp

Revoke a Token#

await sdk.developer.capability.revoke(cap.hash)
// Token immediately invalid — cannot be used again

Use this when a user logs out, or when a sensitive operation is cancelled.


Capability by Layer#

LayerCommon Capabilities
L8 Intelligenceintelligence:agent:run, intelligence:agent:deploy, intelligence:sandbox:execute
L4 Settlementsettlement:intent:create
L5 Identityidentity:record:resolve (usually auto-approved for reads)
L7 DePINinfrastructure:storage:write, infrastructure:compute:allocate
L6 Transporttransport:message:send
L3 Connectorsdeveloper:connector:gmail:send, developer:connector:slack:send

Best Practices#

  • Request capability tokens just before use — not on app startup

  • Use short TTLs for sensitive ops (payments: 300s, deploys: 600s)

  • Always handle GAO-4001 with a re-request + single retry

  • Never share capability tokens between users or sessions

  • For server-side automation, use service tokens with longer TTL (max 24h)

PreviousAuthenticationNextsdk.identity