{
  "$id": "https://glide.co/schemas/agent-banking/v1/_types.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Glide agent-banking shared types",
  "description": "Shared type primitives referenced via $ref by every other schema in the agent-banking vocabulary. Promotion to /v1/* keeps these definitions stable; additive changes only (new enum values, new optional fields) until a major version bump.",
  "channel": "v1",
  "$defs": {
    "uuidV4": {
      "type": "string",
      "description": "Lowercase RFC 4122 v4 UUID. The pattern accepts UUID v1-v8 plus the all-zero and all-F sentinels (used by some seed scripts).",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "examples": ["11111111-1111-4111-8111-111111111111"]
    },
    "isoDateTimeUtc": {
      "type": "string",
      "description": "ISO 8601 / RFC 3339 instant in UTC. The 'Z' suffix is REQUIRED; offsets like '+00:00' are rejected to keep the wire format unambiguous across tRPC, MCP, JWT and Privy serialization boundaries.",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
      "examples": ["2026-04-25T00:00:00.000Z"]
    },
    "unixSecondsPositive": {
      "type": "integer",
      "description": "Unix epoch seconds (UTC), strictly positive. Used for JWT iat/nbf/exp per RFC 7519 §2 NumericDate.",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "amountCents": {
      "type": "integer",
      "description": "Money amount in minor units (cents for USD-shaped currencies; USDC has 6 decimals so we normalize to 1e-2 USD = 1 cent in policy land — see `lib/usdc-units.ts`). Non-negative; max is JS Number.MAX_SAFE_INTEGER.",
      "minimum": 0,
      "maximum": 9007199254740991,
      "examples": [50000]
    },
    "nonNegativeInt": {
      "type": "integer",
      "description": "Non-negative integer up to JS Number.MAX_SAFE_INTEGER.",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "positiveInt": {
      "type": "integer",
      "description": "Strictly positive integer up to JS Number.MAX_SAFE_INTEGER.",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "chainId": {
      "type": "string",
      "description": "Closed vocabulary of supported EVM L1/L2 + Solana + Tempo (EVM L1) + Stellar (non-EVM). Excludes 'bsc' deliberately — USDC on BSC has 18 decimals vs 6 everywhere else, which would silently 10^12-underflow amount-in-cents math in policy eval. Re-enabling requires lib/usdc-units.ts to branch on chain first (PLAN.md F4). Stellar uses 7 decimals on the SAC USDC asset; lib/usdc-units.ts branches on stellar.",
      "enum": [
        "eth",
        "base",
        "arb",
        "op",
        "polygon",
        "sol",
        "tempo",
        "stellar"
      ],
      "examples": ["base"]
    },
    "currencyCode": {
      "type": "string",
      "description": "Currency identifier. Either an ISO 4217 alpha-3 fiat code (e.g. 'USD', 'EUR') or a stablecoin symbol (e.g. 'USDC', 'USDT', 'PYUSD'). Case-insensitive on input but normalized to uppercase server-side.",
      "minLength": 3,
      "maxLength": 8,
      "pattern": "^[A-Za-z][A-Za-z0-9]{2,7}$",
      "examples": ["USDC", "USD", "EUR"]
    },
    "iso3166Alpha2": {
      "type": "string",
      "description": "ISO 3166-1 alpha-2 country code, uppercase. Two ASCII letters.",
      "pattern": "^[A-Z]{2}$",
      "examples": ["US", "GB", "DE"]
    },
    "regionCode": {
      "type": "string",
      "description": "Region identifier — either an ISO 3166-1 alpha-2 country code (`US`, `GB`) or a region tag (`EU`, `LATAM`, `APAC`, `GLOBAL`). 2-8 uppercase ASCII letters. Used in connector/skill regions + dataResidency arrays where the granularity is broader than per-country.",
      "pattern": "^[A-Z]{2,8}$",
      "examples": ["US", "EU", "LATAM", "GLOBAL"]
    },
    "ianaTimezone": {
      "type": "string",
      "description": "IANA tz database name (e.g. 'America/New_York', 'UTC'). Loose pattern — the policy engine resolves via Intl.DateTimeFormat at evaluation time and will fail-closed on unknown zones.",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^(UTC|[A-Za-z][A-Za-z0-9_+\\-]*(?:/[A-Za-z][A-Za-z0-9_+\\-]*)+)$",
      "examples": ["UTC", "America/New_York", "Europe/Berlin"]
    },
    "mccCode": {
      "type": "string",
      "description": "ISO 18245 Merchant Category Code: exactly 4 ASCII digits.",
      "pattern": "^[0-9]{4}$",
      "examples": ["7995", "5411"]
    },
    "hostname": {
      "type": "string",
      "description": "DNS hostname (RFC 1123). Lowercase, no trailing dot, no scheme, no path. Use this for egress-host allowlists.",
      "minLength": 1,
      "maxLength": 253,
      "pattern": "^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$",
      "examples": ["api.bridge.xyz"]
    },
    "httpsUrl": {
      "type": "string",
      "description": "Absolute https:// URL. The http: scheme is rejected to prevent silent downgrade attacks on partner-published manifest links.",
      "format": "uri",
      "pattern": "^https://[^\\s]+$",
      "maxLength": 2048
    },
    "kebabSlug": {
      "type": "string",
      "description": "Lowercase kebab-case identifier. Used for connector + skill slugs that show up in URLs.",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^[a-z0-9][a-z0-9-]*$",
      "examples": ["bridge-payouts", "ap-bill-pay"]
    },
    "semver": {
      "type": "string",
      "description": "Semantic Versioning 2.0.0 string (https://semver.org). Loose pattern — full SemVer (with build/prerelease) is allowed.",
      "minLength": 5,
      "maxLength": 64,
      "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$",
      "examples": ["0.2.0", "1.0.0-rc.1"]
    },
    "agentScope": {
      "type": "string",
      "description": "Closed vocabulary of MCP scopes a grant can carry. Adding a scope is a CODEOWNERS-protected change because the policy engine evaluator must understand the same vocabulary. Wildcard scopes like `treasury:*` are deferred to v1.5+.",
      "enum": [
        "accounts:read",
        "agents:read",
        "payments:initiate",
        "payments:simulate",
        "cards:manage",
        "agent:budget:create",
        "agent:budget:revoke",
        "beneficiary:read",
        "beneficiary:write",
        "kyc:start",
        "x402:pay",
        "x402:receive",
        "audit:stream",
        "treasury:rotate-signer",
        "treasury:yield-allocate"
      ]
    },
    "trustTier": {
      "type": "string",
      "description": "Quality-based trust tier for connectors + skills. `community` is off by default and requires explicit env-var unlock; `verified` ships enabled with per-tenant opt-in; `core` is Glide-maintained reference code.",
      "enum": ["community", "verified", "core"]
    },
    "riskVerdict": {
      "type": "string",
      "description": "Closed enum of policy-engine verdicts. `allow` = proceed; `allow_with_step_up` = proceed only if the principal completes a fresh step-up auth (Privy WebAuthn / passkey); `deny` = refuse.",
      "enum": ["allow", "allow_with_step_up", "deny"]
    },
    "amlPosture": {
      "type": "string",
      "description": "Vendor's AML/sanctions posture. `vendor-screened` = vendor runs sanctions screening before settlement; `pass-through` = vendor relays our screening decision unchanged; `unscreened` = no screening applied (community-tier mock or test connector).",
      "enum": ["vendor-screened", "pass-through", "unscreened"]
    },
    "connectorCapability": {
      "type": "string",
      "description": "Closed vocabulary of connector capabilities the orchestration shell can route to. Capability interface contracts live in `packages/connectors/_base/src/capabilities/*.ts`. Reserved names for forward-compat: a capability NOT in this enum will be rejected at registry boot — adding one requires a schema migration.",
      "enum": [
        "orchestration",
        "kyc",
        "card",
        "screening",
        "chain-receipt",
        "balance",
        "auth",
        "banking",
        "qr-gateway",
        "oauth-authorization-server",
        "attestation",
        "merkle-anchor",
        "timelock-module",
        "recovery"
      ]
    },
    "skillRuntime": {
      "type": "string",
      "description": "Closed vocabulary of agent runtimes a skill targets.",
      "enum": ["claude-desktop", "chatgpt-apps", "vertex", "openclaw", "hermes"]
    },
    "skillCategory": {
      "type": "string",
      "description": "Closed vocabulary of skill categories surfaced in the catalog.",
      "enum": ["ap", "treasury", "consumer", "payroll", "x402"]
    },
    "skillScope": {
      "type": "string",
      "description": "Closed vocabulary of MCP scopes a skill manifest can request. Strict subset of `agentScope` — administrative scopes (`agent:budget:create`, `agent:budget:revoke`, `treasury:rotate-signer`) are intentionally NOT requestable from a skill manifest; they may only be granted via in-app admin actions.",
      "enum": [
        "accounts:read",
        "agents:read",
        "audit:stream",
        "beneficiary:write",
        "cards:manage",
        "payments:initiate",
        "payments:simulate",
        "treasury:yield-allocate",
        "x402:pay",
        "x402:receive"
      ]
    },
    "agentActivityEventKind": {
      "type": "string",
      "description": "Closed vocabulary of agent-activity event kinds streamed to the Trust Console. Reserved values for forward-compat: producers MUST emit one of these; unknown values cause the event to be dropped at ingest.",
      "enum": [
        "tool_call",
        "reasoning_step",
        "risk_verdict",
        "anomaly_detected",
        "consent_prompt",
        "consent_granted",
        "consent_denied",
        "step_up_required",
        "step_up_completed",
        "policy_violation",
        "grant_issued",
        "grant_revoked",
        "kill_switch_triggered"
      ]
    },
    "evmAddress": {
      "type": "string",
      "description": "0x-prefixed 20-byte Ethereum-style address, mixed-case allowed (EIP-55 checksum is verified server-side, not in the schema).",
      "pattern": "^0x[0-9a-fA-F]{40}$",
      "examples": ["0x71C7656EC7ab88b098defB751B7401B5f6d8976F"]
    },
    "solanaAddress": {
      "type": "string",
      "description": "Solana base58 public key, 32-44 chars. Base58 alphabet: `[1-9A-HJ-NP-Za-km-z]`.",
      "pattern": "^[1-9A-HJ-NP-Za-km-z]{32,44}$",
      "examples": ["7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"]
    },
    "chainAddress": {
      "description": "Address on a supported chain. Either an EVM address or Solana base58 pubkey. The accompanying `chain` field disambiguates which form applies.",
      "anyOf": [
        { "$ref": "#/$defs/evmAddress" },
        { "$ref": "#/$defs/solanaAddress" }
      ]
    },
    "txHash": {
      "type": "string",
      "description": "On-chain transaction identifier. EVM: 0x-prefixed 32-byte hex (66 chars). Solana: base58 signature (typically 87-88 chars). Server fetches and re-derives this from the chain RPC — never trust a value passed in via a facilitator response body.",
      "minLength": 1,
      "maxLength": 128,
      "examples": [
        "0xabc123...",
        "5xKf9q5tUJTuT9w8PNMo4WxFf2NAfx1YGv2XrdL5cHvCwJgGEN9pqRUxDvRJSwkV3bKpwSn4cyFFfh4SdVjg6Csa"
      ]
    }
  }
}
