@vaia-lab/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -0
- package/dist/cli.js +205 -0
- package/dist/index.cjs +601 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +521 -0
- package/dist/index.d.ts +521 -0
- package/dist/index.js +576 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/gandia/index.ts","../src/crypto.ts","../src/types.ts","../src/gandia/verify.ts","../src/gandia/jwt.ts","../src/jwt-utils.ts","../src/gandia/respond.ts","../src/gandia/permissions.ts","../src/handeia/index.ts","../src/handeia/verify.ts","../src/handeia/jwt.ts","../src/define.ts"],"sourcesContent":["/**\n * @vaia/sdk — VAIA Platform Integration SDK\n *\n * Provides two namespaces:\n * gandia → Gandia-7 (institutional platform)\n * handeia → Handeia (personal platform)\n *\n * Quick start:\n * import { gandia, handeia, defineCapability, VAIAError } from '@vaia/sdk'\n */\n\n// ─── Platform namespaces ──────────────────────────────────────────────────────\n\nimport * as _gandia from './gandia/index.js'\nimport * as _handeia from './handeia/index.js'\n\nexport const gandia = _gandia\nexport const handeia = _handeia\n\n// ─── defineCapability + manifest ─────────────────────────────────────────────\n\nexport { defineCapability, toManifest } from './define.js'\nexport type { CapabilityConfig, VAIAManifest } from './define.js'\n\n// ─── Shared error class ───────────────────────────────────────────────────────\n\nexport { VAIAError } from './types.js'\n\n// ─── All types (re-exported for consumer convenience) ─────────────────────────\n\nexport type {\n // Core enums\n PublishType,\n EcoTarget,\n NodeType,\n Risk,\n Surface,\n OutputType,\n\n // Contexts\n GandiaContext,\n GandiaTenant,\n GandiaUser,\n HandeiaContext,\n HandeiaUser,\n\n // JWT claims\n GandiaJWTClaims,\n HandeiaJWTClaims,\n\n // Response payloads\n CardPayload,\n TablePayload,\n WidgetPayload,\n ActionPayload,\n AuditRecord,\n RespondOpts,\n SurfaceHandlers,\n\n // Response types\n VAIAResponse,\n CardResponse,\n TableResponse,\n TextResponse,\n WidgetResponse,\n ActionResponse,\n DataResponse,\n ErrorResponse,\n} from './types.js'\n","/**\n * gandia — integration namespace for Gandia-7 (institutional platform).\n *\n * Quick start:\n * import { gandia } from '@vaia/sdk'\n *\n * export async function POST(req: Request) {\n * try {\n * const { ctx } = await gandia.verify(req, process.env.GANDIA_KEY_SECRET!)\n * gandia.require(ctx, 'read:students')\n * const data = await myDb.getStudents(ctx.tenant.id)\n * return gandia.respond.surface(ctx.surface, {\n * card: () => ({ title: 'Total alumnos', value: data.length }),\n * table: () => ({ columns: ['nombre', 'riesgo'], rows: data }),\n * text: () => `${data.length} alumnos en ${ctx.tenant.name}`,\n * })\n * } catch (err) {\n * if (err instanceof VAIAError) return gandia.respond.error(err.message, err.status)\n * throw err\n * }\n * }\n */\n\nexport { verify, isProbe, type VerifyResult } from './verify.js'\nexport * as jwt from './jwt.js'\nexport { respond, make } from './respond.js'\nexport { can, canAll, canAny, require, requireAll } from './permissions.js'\n","/**\n * HMAC-SHA256 utilities using the Web Crypto API.\n * Zero dependencies — works in Node 18+, Edge, Bun, Deno, browsers.\n */\n\nconst enc = new TextEncoder()\n\nfunction hexToBytes(hex: string): Uint8Array {\n if (hex.length % 2 !== 0) throw new Error('Invalid hex string')\n const bytes = new Uint8Array(hex.length / 2)\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16)\n }\n return bytes\n}\n\nasync function importHMACKey(secret: string): Promise<CryptoKey> {\n return crypto.subtle.importKey(\n 'raw',\n enc.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign', 'verify'],\n )\n}\n\n/** Signs `data` with HMAC-SHA256, returns lowercase hex. */\nexport async function hmacSign(secret: string, data: string): Promise<string> {\n const key = await importHMACKey(secret)\n const sig = await crypto.subtle.sign('HMAC', key, enc.encode(data))\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Constant-time HMAC-SHA256 verification.\n * Uses Web Crypto `verify` to avoid timing attacks.\n */\nexport async function hmacVerify(secret: string, data: string, hexSignature: string): Promise<boolean> {\n try {\n const key = await importHMACKey(secret)\n const sigBytes = hexToBytes(hexSignature)\n return await crypto.subtle.verify('HMAC', key, sigBytes, enc.encode(data))\n } catch {\n return false\n }\n}\n","// ─── Core enums ───────────────────────────────────────────────────────────────\n\nexport type PublishType = 'app' | 'ia' | 'skill' | 'eco'\nexport type EcoTarget = 'gandia' | 'handeia' | 'both'\nexport type NodeType = 'widget' | 'artefacto' | 'espacio' | 'skill' | 'agente'\nexport type Risk = 'low' | 'medium' | 'high'\nexport type Surface = 'card' | 'table' | 'text' | 'widget' | 'action' | 'data'\nexport type OutputType = Surface\n\n// ─── Gandia context ───────────────────────────────────────────────────────────\n\nexport interface GandiaTenant {\n id: string\n name: string\n sector: string\n}\n\nexport interface GandiaUser {\n id: string\n role: string\n email?: string | undefined\n}\n\n/** Context injected by GAIA on every invoke call to the developer's server. */\nexport interface GandiaContext {\n capability_id: string\n call_id: string\n tenant: GandiaTenant\n user: GandiaUser\n permissions: string[]\n trigger: 'user_query' | 'gaia_invoke' | 'event'\n /** Surface HAIA wants to render — determines which respond.* to use. */\n surface: Surface\n query?: string | undefined\n}\n\n// ─── Handeia context ──────────────────────────────────────────────────────────\n\nexport interface HandeiaUser {\n id: string\n email?: string | undefined\n name?: string | undefined\n}\n\n/** Context injected by HAIA on every invoke call to the developer's server. */\nexport interface HandeiaContext {\n capability_id: string\n call_id: string\n user: HandeiaUser\n permissions: string[]\n trigger: 'user_action' | 'haia_invoke' | 'schedule'\n /** Surface HAIA wants to render. */\n surface: Surface\n query?: string | undefined\n}\n\n// ─── JWT claims ───────────────────────────────────────────────────────────────\n\nexport interface GandiaJWTClaims {\n sub: string // user_id\n tenant_id: string\n email?: string | undefined\n role?: string | undefined\n permissions: string[]\n iat: number\n exp: number\n}\n\nexport interface HandeiaJWTClaims {\n sub: string // user_id\n email?: string | undefined\n name?: string | undefined\n permissions: string[]\n iat: number\n exp: number\n}\n\n// ─── Response payloads ────────────────────────────────────────────────────────\n\nexport interface AuditRecord {\n data_sources?: string[] | undefined\n records_accessed?: number | undefined\n [key: string]: unknown\n}\n\nexport interface RespondOpts {\n call_id?: string | undefined\n audit?: AuditRecord | undefined\n}\n\nexport interface CardPayload {\n title: string\n value?: string | number | undefined\n unit?: string | undefined\n trend?: 'up' | 'down' | 'neutral' | undefined\n icon?: string | undefined\n subtitle?: string | undefined\n color?: string | undefined\n [key: string]: unknown\n}\n\nexport interface TablePayload {\n columns: string[] | Array<{ key: string; label: string; type?: string | undefined }>\n rows: Array<Record<string, unknown>>\n total?: number | undefined\n page?: number | undefined\n per_page?: number | undefined\n}\n\nexport interface WidgetPayload {\n url: string\n height?: number | string | undefined\n width?: number | string | undefined\n meta?: Record<string, unknown> | undefined\n}\n\nexport interface ActionPayload {\n type: string\n label?: string | undefined\n params?: Record<string, unknown> | undefined\n confirm?: boolean | undefined\n destructive?: boolean | undefined\n}\n\n// ─── Typed VAIA response objects (returned by make.*) ────────────────────────\n\ninterface BaseVAIAResponse {\n ok: true\n call_id?: string | undefined\n audit?: AuditRecord | undefined\n}\n\nexport type CardResponse = BaseVAIAResponse & { output_type: 'card'; data: CardPayload }\nexport type TableResponse = BaseVAIAResponse & { output_type: 'table'; data: TablePayload }\nexport type TextResponse = BaseVAIAResponse & { output_type: 'text'; text: string; markdown?: boolean | undefined }\nexport type WidgetResponse = BaseVAIAResponse & { output_type: 'widget'; data: WidgetPayload }\nexport type ActionResponse = BaseVAIAResponse & { output_type: 'action'; data: ActionPayload }\nexport type DataResponse = BaseVAIAResponse & { output_type: 'data'; data: Record<string, unknown> }\nexport type ErrorResponse = { ok: false; error: string; code?: string | undefined }\n\nexport type VAIAResponse =\n | CardResponse\n | TableResponse\n | TextResponse\n | WidgetResponse\n | ActionResponse\n | DataResponse\n\n// ─── Surface handler map ──────────────────────────────────────────────────────\n\nexport type SurfaceHandlers = Partial<{\n card: () => CardPayload | Promise<CardPayload>\n table: () => TablePayload | Promise<TablePayload>\n text: () => string | Promise<string>\n widget: () => WidgetPayload | Promise<WidgetPayload>\n action: () => ActionPayload | Promise<ActionPayload>\n data: () => Record<string, unknown> | Promise<Record<string, unknown>>\n}>\n\n// ─── Capability definition ────────────────────────────────────────────────────\n\nexport interface SurfaceConfig {\n endpoint: string\n description?: string | undefined\n}\n\nexport interface CapabilityConfig {\n /** Unique capability ID — reverse domain: 'mx.mi-capacidad' */\n id: string\n name: string\n version: string\n /** Which VAIA platform(s) this capability targets. */\n target: EcoTarget\n type: PublishType\n level?: 'widget' | 'artefacto' | 'espacio' | undefined\n sector: string\n /** Which surfaces the capability can respond to, and their invoke endpoint. */\n surfaces: Partial<Record<Surface, SurfaceConfig>>\n permissions: string[]\n risk: Risk\n description?: string | undefined\n tags?: string[] | undefined\n /** Set to true if your app has its own login (triggers JWT bypass flow). */\n has_own_auth?: boolean | undefined\n stores_data?: boolean | undefined\n trains_models?: boolean | undefined\n requires_consent?: boolean | undefined\n}\n\n// ─── Errors ───────────────────────────────────────────────────────────────────\n\nexport class VAIAError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly status: number = 500,\n ) {\n super(message)\n this.name = 'VAIAError'\n }\n}\n","/**\n * gandia.verify — verifies an incoming invoke call from Gandia-7.\n *\n * Checks:\n * 1. X-Gandia-Signature (HMAC-SHA256 over timestamp + \".\" + raw body)\n * 2. X-Gandia-Timestamp within ±5 minutes (replay attack prevention)\n * 3. Parses and types the body as GandiaContext\n *\n * Usage:\n * const { ctx } = await verify(request, process.env.GANDIA_KEY_SECRET!)\n */\n\nimport { hmacVerify } from '../crypto.js'\nimport { VAIAError, type GandiaContext, type Surface } from '../types.js'\n\nconst REPLAY_WINDOW_MS = 5 * 60 * 1000 // 5 minutes\nconst PROBE_HEADER = 'x-gandia-probe'\n\n/** Raw body of the invoke call. Returned alongside ctx so you don't re-read the stream. */\nexport interface VerifyResult {\n ctx: GandiaContext\n raw: string\n}\n\n/**\n * Call at the top of your `/api/gandia/invoke` route handler.\n * Throws VAIAError if the signature is invalid or the timestamp is stale.\n */\nexport async function verify(request: Request, secret: string): Promise<VerifyResult> {\n const rawBody = await request.text()\n const headers = request.headers\n\n const sigHeader = headers.get('x-gandia-signature') ?? ''\n const tsHeader = headers.get('x-gandia-timestamp') ?? ''\n const callId = headers.get('x-gandia-call-id') ?? ''\n\n // Health probe from test-connection — no signature required\n if (headers.get(PROBE_HEADER) === '1') {\n return { ctx: buildProbeCtx(callId), raw: rawBody }\n }\n\n if (!sigHeader || !tsHeader) {\n throw new VAIAError(\n 'Faltan headers de autenticación (X-Gandia-Signature, X-Gandia-Timestamp)',\n 'MISSING_AUTH_HEADERS',\n 401,\n )\n }\n\n // Replay attack check\n const ts = parseInt(tsHeader, 10)\n if (isNaN(ts) || Math.abs(Date.now() - ts) > REPLAY_WINDOW_MS) {\n throw new VAIAError('Timestamp fuera de ventana (±5 min)', 'TIMESTAMP_OUT_OF_RANGE', 401)\n }\n\n // Strip \"sha256=\" prefix if present\n const hexSig = sigHeader.startsWith('sha256=') ? sigHeader.slice(7) : sigHeader\n\n // HMAC verification — constant-time via Web Crypto\n const signedData = `${tsHeader}.${rawBody}`\n const valid = await hmacVerify(secret, signedData, hexSig)\n if (!valid) {\n throw new VAIAError('Firma HMAC inválida', 'HMAC_INVALID', 401)\n }\n\n // Parse body\n let body: unknown\n try {\n body = JSON.parse(rawBody)\n } catch {\n throw new VAIAError('Body no es JSON válido', 'BODY_PARSE_ERROR', 400)\n }\n\n const ctx = parseContext(body, callId)\n return { ctx, raw: rawBody }\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction parseContext(body: unknown, fallbackCallId: string): GandiaContext {\n if (typeof body !== 'object' || body === null) {\n throw new VAIAError('Body inválido', 'BODY_INVALID', 400)\n }\n\n const b = body as Record<string, unknown>\n\n return {\n capability_id: str(b, 'capability_id'),\n call_id: str(b, 'call_id', fallbackCallId),\n tenant: {\n id: nestedStr(b, 'tenant', 'id'),\n name: nestedStr(b, 'tenant', 'name'),\n sector: nestedStr(b, 'tenant', 'sector'),\n },\n user: {\n id: nestedStr(b, 'user', 'id'),\n role: nestedStr(b, 'user', 'role'),\n email: nestedStrOpt(b, 'user', 'email'),\n },\n permissions: arr(b, 'permissions'),\n trigger: str(b, 'context.trigger', 'gaia_invoke') as GandiaContext['trigger'],\n surface: str(b, 'context.surface', 'data') as Surface,\n query: nestedStrOpt(b, 'context', 'query'),\n }\n}\n\nfunction buildProbeCtx(callId: string): GandiaContext {\n return {\n capability_id: '__probe__',\n call_id: callId || crypto.randomUUID(),\n tenant: { id: '__probe__', name: '__probe__', sector: '__probe__' },\n user: { id: '__probe__', role: '__probe__' },\n permissions: [],\n trigger: 'gaia_invoke',\n surface: 'data',\n }\n}\n\nfunction str(obj: Record<string, unknown>, key: string, fallback = ''): string {\n // Support dot notation: 'context.trigger'\n const parts = key.split('.')\n let cur: unknown = obj\n for (const part of parts) {\n if (typeof cur !== 'object' || cur === null) return fallback\n cur = (cur as Record<string, unknown>)[part]\n }\n return typeof cur === 'string' ? cur : fallback\n}\n\nfunction nestedStr(\n obj: Record<string, unknown>,\n parent: string,\n key: string,\n fallback = '',\n): string {\n const p = obj[parent]\n if (typeof p !== 'object' || p === null) return fallback\n const v = (p as Record<string, unknown>)[key]\n return typeof v === 'string' ? v : fallback\n}\n\nfunction nestedStrOpt(\n obj: Record<string, unknown>,\n parent: string,\n key: string,\n): string | undefined {\n const p = obj[parent]\n if (typeof p !== 'object' || p === null) return undefined\n const v = (p as Record<string, unknown>)[key]\n return typeof v === 'string' ? v : undefined\n}\n\nfunction arr(obj: Record<string, unknown>, key: string): string[] {\n const v = obj[key]\n if (!Array.isArray(v)) return []\n return v.filter((x): x is string => typeof x === 'string')\n}\n\n/** Quick check — use before calling verify() if you want to short-circuit probes. */\nexport function isProbe(request: Request): boolean {\n return request.headers.get(PROBE_HEADER) === '1'\n}\n","/**\n * gandia.jwt — JWT helpers for iframe auth bypass.\n *\n * When Gandia-7 opens a developer's app as an iframe, it appends:\n * ?gandia_token=<signed_jwt>\n *\n * The developer verifies the token, extracts the user/tenant claims,\n * and creates a session — skipping their own login page.\n *\n * Usage (server-side):\n * const claims = await gandia.jwt.verify(token, process.env.GANDIA_KEY_SECRET!)\n * // → { sub, tenant_id, email, role, permissions, exp, iat }\n *\n * Usage (VAIA-side, when generating tokens for developer iframes):\n * const token = await gandia.jwt.sign({ sub: userId, tenant_id, ... }, secret, { expiresIn: 3600 })\n */\n\nimport { jwtSign, jwtVerify } from '../jwt-utils.js'\nimport type { GandiaJWTClaims } from '../types.js'\n\nexport interface GandiaJWTSignInput {\n sub: string // user_id\n tenant_id: string\n email?: string | undefined\n role?: string | undefined\n permissions?: string[] | undefined\n}\n\nexport interface SignOpts {\n /** Seconds until expiry. Default: 3600 (1 hour). */\n expiresIn?: number | undefined\n}\n\nconst DEFAULT_EXPIRES_IN = 3600\n\n/** Signs a new Gandia iframe JWT. Typically called by Gandia-7, not by the developer. */\nexport async function sign(\n input: GandiaJWTSignInput,\n secret: string,\n opts: SignOpts = {},\n): Promise<string> {\n const now = Math.floor(Date.now() / 1000)\n return jwtSign(\n {\n ...input,\n permissions: input.permissions ?? [],\n iat: now,\n exp: now + (opts.expiresIn ?? DEFAULT_EXPIRES_IN),\n },\n secret,\n )\n}\n\n/** Verifies a Gandia iframe JWT and returns its claims. Throws VAIAError on failure. */\nexport async function verify(token: string, secret: string): Promise<GandiaJWTClaims> {\n return jwtVerify<GandiaJWTClaims>(token, secret)\n}\n\n/**\n * Extracts `gandia_token` from a URL and verifies it.\n * Convenience for iframe entry-point routes.\n *\n * const claims = await gandia.jwt.fromUrl(request.url, secret)\n */\nexport async function fromUrl(url: string | URL, secret: string): Promise<GandiaJWTClaims> {\n const u = typeof url === 'string' ? new URL(url) : url\n const token = u.searchParams.get('gandia_token')\n if (!token) {\n throw new Error('gandia_token no encontrado en la URL')\n }\n return verify(token, secret)\n}\n","/**\n * Minimal HS256 JWT implementation using Web Crypto.\n * No third-party dependencies.\n */\n\nimport { VAIAError } from './types.js'\n\nconst enc = new TextEncoder()\n\nfunction b64urlEncode(data: ArrayBuffer | string): string {\n const str =\n typeof data === 'string'\n ? data\n : String.fromCharCode(...new Uint8Array(data))\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '')\n}\n\nfunction b64urlDecode(str: string): string {\n const padded = str.replace(/-/g, '+').replace(/_/g, '/')\n const pad = padded.length % 4\n return atob(pad ? padded + '='.repeat(4 - pad) : padded)\n}\n\nasync function importHMACKey(secret: string): Promise<CryptoKey> {\n return crypto.subtle.importKey(\n 'raw',\n enc.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign', 'verify'],\n )\n}\n\nconst HEADER = b64urlEncode(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))\n\n/** Creates a signed HS256 JWT. */\nexport async function jwtSign(\n payload: Record<string, unknown>,\n secret: string,\n): Promise<string> {\n const body = b64urlEncode(JSON.stringify(payload))\n const unsigned = `${HEADER}.${body}`\n const key = await importHMACKey(secret)\n const sig = await crypto.subtle.sign('HMAC', key, enc.encode(unsigned))\n return `${unsigned}.${b64urlEncode(sig)}`\n}\n\n/** Verifies an HS256 JWT and returns its payload. Throws VAIAError on failure. */\nexport async function jwtVerify<T extends object>(\n token: string,\n secret: string,\n): Promise<T> {\n const parts = token.split('.')\n if (parts.length !== 3) {\n throw new VAIAError('JWT malformado', 'JWT_MALFORMED', 401)\n }\n\n const [header, body, sig] = parts as [string, string, string]\n const unsigned = `${header}.${body}`\n\n const key = await importHMACKey(secret)\n const sigBytes = Uint8Array.from(b64urlDecode(sig), c => c.charCodeAt(0))\n const valid = await crypto.subtle.verify('HMAC', key, sigBytes, enc.encode(unsigned))\n\n if (!valid) {\n throw new VAIAError('Firma JWT inválida', 'JWT_SIGNATURE_INVALID', 401)\n }\n\n let payload: T & { exp?: number; iat?: number }\n try {\n payload = JSON.parse(b64urlDecode(body)) as T & { exp?: number; iat?: number }\n } catch {\n throw new VAIAError('JWT payload inválido', 'JWT_PAYLOAD_INVALID', 401)\n }\n\n if (typeof payload.exp === 'number' && Date.now() / 1000 > payload.exp) {\n throw new VAIAError('JWT expirado', 'JWT_EXPIRED', 401)\n }\n\n return payload as T\n}\n","/**\n * gandia.respond — typed response builders.\n *\n * Each method returns a Web API Response with the correct VAIA envelope.\n * HAIA reads `output_type` to decide how to render the result.\n *\n * For non-Response frameworks (Express, Fastify), use gandia.make.* instead.\n *\n * Usage:\n * // Returns Web API Response\n * return gandia.respond.card({ title: 'Riesgo', value: 72, unit: '%' })\n *\n * // Multi-surface: GAIA tells you which surface it wants via ctx.surface\n * return gandia.respond.surface(ctx.surface, {\n * card: () => ({ title: 'Riesgo', value: 72 }),\n * table: () => ({ columns: ['alumno', 'score'], rows }),\n * text: () => `El riesgo del grupo es ${risk}%`,\n * })\n */\n\nimport type {\n CardPayload,\n TablePayload,\n WidgetPayload,\n ActionPayload,\n RespondOpts,\n Surface,\n SurfaceHandlers,\n VAIAResponse,\n CardResponse,\n TableResponse,\n TextResponse,\n WidgetResponse,\n ActionResponse,\n DataResponse,\n} from '../types.js'\nimport { VAIAError } from '../types.js'\n\n// ─── JSON helpers ─────────────────────────────────────────────────────────────\n\nconst JSON_HEADERS = { 'Content-Type': 'application/json' }\n\nfunction toResponse(body: VAIAResponse | { ok: false; error: string }, status = 200): Response {\n return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS })\n}\n\n// ─── make.* — plain objects (framework-agnostic) ─────────────────────────────\n\nexport const make = {\n card(payload: CardPayload, opts: RespondOpts = {}): CardResponse {\n return { ok: true, output_type: 'card', data: payload, ...opts }\n },\n\n table(payload: TablePayload, opts: RespondOpts = {}): TableResponse {\n return { ok: true, output_type: 'table', data: payload, ...opts }\n },\n\n text(content: string, opts: RespondOpts & { markdown?: boolean } = {}): TextResponse {\n const { markdown, ...rest } = opts\n return { ok: true, output_type: 'text', text: content, markdown, ...rest }\n },\n\n widget(payload: WidgetPayload, opts: RespondOpts = {}): WidgetResponse {\n return { ok: true, output_type: 'widget', data: payload, ...opts }\n },\n\n action(payload: ActionPayload, opts: RespondOpts = {}): ActionResponse {\n return { ok: true, output_type: 'action', data: payload, ...opts }\n },\n\n data(payload: Record<string, unknown>, opts: RespondOpts = {}): DataResponse {\n return { ok: true, output_type: 'data', data: payload, ...opts }\n },\n} as const\n\n// ─── respond.* — Web API Response ────────────────────────────────────────────\n\nexport const respond = {\n /** A compact card: title, value, unit, trend, etc. */\n card(payload: CardPayload, opts: RespondOpts = {}): Response {\n return toResponse(make.card(payload, opts))\n },\n\n /** Tabular data with columns + rows. */\n table(payload: TablePayload, opts: RespondOpts = {}): Response {\n return toResponse(make.table(payload, opts))\n },\n\n /** Plain text or markdown — shown in chat or narrative views. */\n text(content: string, opts: RespondOpts & { markdown?: boolean } = {}): Response {\n return toResponse(make.text(content, opts))\n },\n\n /** An iframe pointing to the developer's own UI. */\n widget(payload: WidgetPayload, opts: RespondOpts = {}): Response {\n return toResponse(make.widget(payload, opts))\n },\n\n /** Trigger an action (mutation, navigation, confirm dialog). */\n action(payload: ActionPayload, opts: RespondOpts = {}): Response {\n return toResponse(make.action(payload, opts))\n },\n\n /** Arbitrary JSON — HAIA decides how to render based on shape. */\n data(payload: Record<string, unknown>, opts: RespondOpts = {}): Response {\n return toResponse(make.data(payload, opts))\n },\n\n /** Simple 200 OK — useful for probe responses. */\n ok(opts: RespondOpts = {}): Response {\n return toResponse(make.data({ status: 'ok' }, opts))\n },\n\n /** Returns a 4xx/5xx error response. */\n error(message: string, status = 500, code?: string): Response {\n return toResponse({ ok: false, error: message, ...(code ? { code } : {}) }, status)\n },\n\n /**\n * Multi-surface responder.\n * GAIA sends `ctx.surface` telling you what to render.\n * Map each surface to its handler and this picks the right one.\n *\n * return gandia.respond.surface(ctx.surface, {\n * card: () => ({ title: 'Riesgo', value: 72, unit: '%' }),\n * table: () => ({ columns: [...], rows: [...] }),\n * text: () => `El riesgo es 72%`,\n * }, opts)\n */\n async surface(\n surface: Surface,\n handlers: SurfaceHandlers,\n opts: RespondOpts = {},\n ): Promise<Response> {\n const handler = handlers[surface]\n\n if (!handler) {\n // Fallback cascade: data > text > first available handler\n const fallback =\n handlers.data ?? handlers.text ?? Object.values(handlers).find(Boolean)\n if (!fallback) {\n throw new VAIAError(\n `Surface '${surface}' no soportada por esta capacidad`,\n 'SURFACE_NOT_SUPPORTED',\n 422,\n )\n }\n return respond.surface(\n handlers.data ? 'data' : handlers.text ? 'text' : (Object.keys(handlers)[0] as Surface),\n handlers,\n opts,\n )\n }\n\n switch (surface) {\n case 'card': return respond.card(await (handlers.card!)(), opts)\n case 'table': return respond.table(await (handlers.table!)(), opts)\n case 'text': return respond.text(await (handlers.text!)(), opts)\n case 'widget': return respond.widget(await (handlers.widget!)(), opts)\n case 'action': return respond.action(await (handlers.action!)(), opts)\n case 'data': return respond.data(await (handlers.data!)(), opts)\n default: return respond.data(await (handlers.data ?? handlers.text ?? (() => ({})))(), opts)\n }\n },\n} as const\n","/**\n * gandia.can / gandia.require — permission helpers.\n *\n * Usage:\n * if (!gandia.can(ctx, 'read:students')) return gandia.respond.error('Forbidden', 403)\n * gandia.require(ctx, 'write:alerts') // throws VAIAError 403 if missing\n *\n * Supports wildcard scopes:\n * 'read:*' — matches all read permissions\n * 'read:students' — exact match\n */\n\nimport { VAIAError, type GandiaContext } from '../types.js'\n\nfunction matches(permission: string, granted: string[]): boolean {\n if (granted.includes(permission)) return true\n // wildcard: 'read:*' grants 'read:students'\n const [action] = permission.split(':')\n return granted.includes(`${action}:*`)\n}\n\n/** Returns true if the context has the given permission. */\nexport function can(ctx: Pick<GandiaContext, 'permissions'>, permission: string): boolean {\n return matches(permission, ctx.permissions)\n}\n\n/** Returns true if the context has ALL listed permissions. */\nexport function canAll(ctx: Pick<GandiaContext, 'permissions'>, ...permissions: string[]): boolean {\n return permissions.every(p => matches(p, ctx.permissions))\n}\n\n/** Returns true if the context has ANY of the listed permissions. */\nexport function canAny(ctx: Pick<GandiaContext, 'permissions'>, ...permissions: string[]): boolean {\n return permissions.some(p => matches(p, ctx.permissions))\n}\n\n/** Throws VAIAError 403 if the context does NOT have the given permission. */\nexport function require(ctx: Pick<GandiaContext, 'permissions'>, permission: string): void {\n if (!matches(permission, ctx.permissions)) {\n throw new VAIAError(\n `Permiso requerido: ${permission}`,\n 'PERMISSION_DENIED',\n 403,\n )\n }\n}\n\n/** Throws VAIAError 403 if the context does NOT have ALL listed permissions. */\nexport function requireAll(ctx: Pick<GandiaContext, 'permissions'>, ...permissions: string[]): void {\n const missing = permissions.filter(p => !matches(p, ctx.permissions))\n if (missing.length > 0) {\n throw new VAIAError(\n `Permisos requeridos: ${missing.join(', ')}`,\n 'PERMISSION_DENIED',\n 403,\n )\n }\n}\n","/**\n * handeia — integration namespace for Handeia (personal platform).\n *\n * Quick start:\n * import { handeia } from '@vaia/sdk'\n *\n * export async function POST(req: Request) {\n * try {\n * const { ctx } = await handeia.verify(req, process.env.HANDEIA_KEY_SECRET!)\n * const profile = await myDb.getProfile(ctx.user.id)\n * return handeia.respond.surface(ctx.surface, {\n * card: () => ({ title: profile.name, subtitle: profile.role }),\n * text: () => `Hola ${profile.name}`,\n * })\n * } catch (err) {\n * if (err instanceof VAIAError) return handeia.respond.error(err.message, err.status)\n * throw err\n * }\n * }\n */\n\nexport { verify, isProbe, type HandeiaVerifyResult } from './verify.js'\nexport * as jwt from './jwt.js'\n\n// handeia shares the same respond/make API as gandia\nexport { respond, make } from '../gandia/respond.js'\n\n// Permission helpers (work the same — ctx.permissions is always a string[])\nexport { can, canAll, canAny, require, requireAll } from '../gandia/permissions.js'\n","/**\n * handeia.verify — verifies an incoming invoke call from Handeia.\n * Same HMAC protocol as gandia.verify but with Handeia-specific headers\n * and a HandeiaContext (user personal, no tenant).\n */\n\nimport { hmacVerify } from '../crypto.js'\nimport { VAIAError, type HandeiaContext, type Surface } from '../types.js'\n\nconst REPLAY_WINDOW_MS = 5 * 60 * 1000\nconst PROBE_HEADER = 'x-handeia-probe'\n\nexport interface HandeiaVerifyResult {\n ctx: HandeiaContext\n raw: string\n}\n\n/**\n * Call at the top of your `/api/handeia/invoke` route handler.\n * Throws VAIAError if the signature is invalid or the timestamp is stale.\n */\nexport async function verify(request: Request, secret: string): Promise<HandeiaVerifyResult> {\n const rawBody = await request.text()\n const headers = request.headers\n\n const sigHeader = headers.get('x-handeia-signature') ?? ''\n const tsHeader = headers.get('x-handeia-timestamp') ?? ''\n const callId = headers.get('x-handeia-call-id') ?? ''\n\n if (headers.get(PROBE_HEADER) === '1') {\n return { ctx: buildProbeCtx(callId), raw: rawBody }\n }\n\n if (!sigHeader || !tsHeader) {\n throw new VAIAError(\n 'Faltan headers de autenticación (X-Handeia-Signature, X-Handeia-Timestamp)',\n 'MISSING_AUTH_HEADERS',\n 401,\n )\n }\n\n const ts = parseInt(tsHeader, 10)\n if (isNaN(ts) || Math.abs(Date.now() - ts) > REPLAY_WINDOW_MS) {\n throw new VAIAError('Timestamp fuera de ventana (±5 min)', 'TIMESTAMP_OUT_OF_RANGE', 401)\n }\n\n const hexSig = sigHeader.startsWith('sha256=') ? sigHeader.slice(7) : sigHeader\n const signedData = `${tsHeader}.${rawBody}`\n const valid = await hmacVerify(secret, signedData, hexSig)\n\n if (!valid) {\n throw new VAIAError('Firma HMAC inválida', 'HMAC_INVALID', 401)\n }\n\n let body: unknown\n try {\n body = JSON.parse(rawBody)\n } catch {\n throw new VAIAError('Body no es JSON válido', 'BODY_PARSE_ERROR', 400)\n }\n\n const ctx = parseContext(body, callId)\n return { ctx, raw: rawBody }\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction parseContext(body: unknown, fallbackCallId: string): HandeiaContext {\n if (typeof body !== 'object' || body === null) {\n throw new VAIAError('Body inválido', 'BODY_INVALID', 400)\n }\n\n const b = body as Record<string, unknown>\n const user = (b['user'] ?? {}) as Record<string, unknown>\n const ctx = (b['context'] ?? {}) as Record<string, unknown>\n\n return {\n capability_id: s(b['capability_id']),\n call_id: s(b['call_id'], fallbackCallId),\n user: {\n id: s(user['id']),\n email: sOpt(user['email']),\n name: sOpt(user['name']),\n },\n permissions: arr(b['permissions']),\n trigger: s(ctx['trigger'], 'haia_invoke') as HandeiaContext['trigger'],\n surface: s(ctx['surface'], 'data') as Surface,\n query: sOpt(ctx['query']),\n }\n}\n\nfunction buildProbeCtx(callId: string): HandeiaContext {\n return {\n capability_id: '__probe__',\n call_id: callId || crypto.randomUUID(),\n user: { id: '__probe__' },\n permissions: [],\n trigger: 'haia_invoke',\n surface: 'data',\n }\n}\n\nfunction s(v: unknown, fallback = ''): string {\n return typeof v === 'string' ? v : fallback\n}\nfunction sOpt(v: unknown): string | undefined {\n return typeof v === 'string' ? v : undefined\n}\nfunction arr(v: unknown): string[] {\n return Array.isArray(v) ? v.filter((x): x is string => typeof x === 'string') : []\n}\n\nexport function isProbe(request: Request): boolean {\n return request.headers.get(PROBE_HEADER) === '1'\n}\n","/**\n * handeia.jwt — JWT helpers for Handeia iframe auth bypass.\n * Same pattern as gandia.jwt but for personal context (no tenant).\n */\n\nimport { jwtSign, jwtVerify } from '../jwt-utils.js'\nimport type { HandeiaJWTClaims } from '../types.js'\n\nexport interface HandeiaJWTSignInput {\n sub: string // user_id\n email?: string | undefined\n name?: string | undefined\n permissions?: string[] | undefined\n}\n\nexport interface SignOpts {\n expiresIn?: number | undefined\n}\n\nconst DEFAULT_EXPIRES_IN = 3600\n\nexport async function sign(\n input: HandeiaJWTSignInput,\n secret: string,\n opts: SignOpts = {},\n): Promise<string> {\n const now = Math.floor(Date.now() / 1000)\n return jwtSign(\n {\n ...input,\n permissions: input.permissions ?? [],\n iat: now,\n exp: now + (opts.expiresIn ?? DEFAULT_EXPIRES_IN),\n },\n secret,\n )\n}\n\nexport async function verify(token: string, secret: string): Promise<HandeiaJWTClaims> {\n return jwtVerify<HandeiaJWTClaims>(token, secret)\n}\n\n/** Extracts and verifies `handeia_token` from a URL. */\nexport async function fromUrl(url: string | URL, secret: string): Promise<HandeiaJWTClaims> {\n const u = typeof url === 'string' ? new URL(url) : url\n const token = u.searchParams.get('handeia_token')\n if (!token) throw new Error('handeia_token no encontrado en la URL')\n return verify(token, secret)\n}\n","/**\n * defineCapability — declares a VAIA capability in code.\n *\n * This is both a type-safety layer (catches config errors at compile time)\n * and the source of truth for `npx vaia manifest` (generates gandia.manifest.json).\n *\n * The Shazam engine detects `defineCapability` in your code and reads the\n * config with 100% confidence — no manual confirmation needed in the portal.\n *\n * Usage (vaia.config.ts in project root):\n * import { defineCapability } from '@vaia/sdk'\n *\n * export default defineCapability({\n * id: 'mx.monitor-riesgo-academico',\n * name: 'Monitor de Riesgo Académico',\n * version: '1.0.0',\n * target: 'gandia',\n * type: 'app',\n * level: 'artefacto',\n * sector: 'educacion',\n * surfaces: {\n * card: { endpoint: '/api/gandia/invoke' },\n * table: { endpoint: '/api/gandia/invoke' },\n * text: { endpoint: '/api/gandia/invoke' },\n * },\n * permissions: ['read:students', 'read:grades', 'write:alerts'],\n * risk: 'medium',\n * })\n */\n\nimport type { CapabilityConfig, EcoTarget, Risk, Surface } from './types.js'\n\nexport type { CapabilityConfig }\n\nexport interface VAIAManifest {\n schema: '1.0'\n capability_id: string\n name: string\n version: string\n target: EcoTarget | EcoTarget[]\n type: string\n level?: string | undefined\n sector: string\n surfaces: string[]\n permissions: string[]\n risk: Risk\n has_own_auth: boolean\n stores_data: boolean\n trains_models: boolean\n requires_consent: boolean\n description?: string | undefined\n tags?: string[] | undefined\n linked: boolean\n generated_by: '@vaia/sdk'\n generated_at: string\n}\n\n/** Validates and returns the capability config. Throws if required fields are missing. */\nexport function defineCapability(config: CapabilityConfig): CapabilityConfig {\n const required: Array<keyof CapabilityConfig> = ['id', 'name', 'version', 'target', 'type', 'sector', 'permissions', 'risk']\n for (const key of required) {\n if (config[key] === undefined || config[key] === '') {\n throw new Error(`[@vaia/sdk] defineCapability: campo requerido faltante: '${key}'`)\n }\n }\n\n if (!config.id.includes('.')) {\n throw new Error(\n `[@vaia/sdk] defineCapability: 'id' debe usar formato reverse-domain (ej. 'mx.mi-capacidad'). Recibido: '${config.id}'`,\n )\n }\n\n if (Object.keys(config.surfaces).length === 0) {\n throw new Error(`[@vaia/sdk] defineCapability: 'surfaces' no puede estar vacío. Define al menos un surface con su endpoint.`)\n }\n\n return config\n}\n\n/** Converts a CapabilityConfig to a gandia.manifest.json object. */\nexport function toManifest(config: CapabilityConfig): VAIAManifest {\n const surfaces = Object.keys(config.surfaces) as Surface[]\n\n return {\n schema: '1.0',\n capability_id: config.id,\n name: config.name,\n version: config.version,\n target: config.target === 'both' ? ['gandia', 'handeia'] : config.target,\n type: config.type,\n level: config.level,\n sector: config.sector,\n surfaces,\n permissions: config.permissions,\n risk: config.risk,\n has_own_auth: config.has_own_auth ?? false,\n stores_data: config.stores_data ?? false,\n trains_models: config.trains_models ?? false,\n requires_consent: config.requires_consent ?? false,\n description: config.description,\n tags: config.tags,\n linked: config.target === 'both',\n generated_by: '@vaia/sdk',\n generated_at: new Date().toISOString(),\n }\n}\n"],"mappings":"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","names":["require","verify","enc","str","importHMACKey","verify","require","isProbe","jwt_exports","require","verify","REPLAY_WINDOW_MS","PROBE_HEADER","verify","buildProbeCtx","parseContext","arr","isProbe","jwt_exports","fromUrl","sign","verify","DEFAULT_EXPIRES_IN","sign","verify","fromUrl"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
type PublishType = 'app' | 'ia' | 'skill' | 'eco';
|
|
2
|
+
type EcoTarget = 'gandia' | 'handeia' | 'both';
|
|
3
|
+
type NodeType = 'widget' | 'artefacto' | 'espacio' | 'skill' | 'agente';
|
|
4
|
+
type Risk = 'low' | 'medium' | 'high';
|
|
5
|
+
type Surface = 'card' | 'table' | 'text' | 'widget' | 'action' | 'data';
|
|
6
|
+
type OutputType = Surface;
|
|
7
|
+
interface GandiaTenant {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
sector: string;
|
|
11
|
+
}
|
|
12
|
+
interface GandiaUser {
|
|
13
|
+
id: string;
|
|
14
|
+
role: string;
|
|
15
|
+
email?: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** Context injected by GAIA on every invoke call to the developer's server. */
|
|
18
|
+
interface GandiaContext {
|
|
19
|
+
capability_id: string;
|
|
20
|
+
call_id: string;
|
|
21
|
+
tenant: GandiaTenant;
|
|
22
|
+
user: GandiaUser;
|
|
23
|
+
permissions: string[];
|
|
24
|
+
trigger: 'user_query' | 'gaia_invoke' | 'event';
|
|
25
|
+
/** Surface HAIA wants to render — determines which respond.* to use. */
|
|
26
|
+
surface: Surface;
|
|
27
|
+
query?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
interface HandeiaUser {
|
|
30
|
+
id: string;
|
|
31
|
+
email?: string | undefined;
|
|
32
|
+
name?: string | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Context injected by HAIA on every invoke call to the developer's server. */
|
|
35
|
+
interface HandeiaContext {
|
|
36
|
+
capability_id: string;
|
|
37
|
+
call_id: string;
|
|
38
|
+
user: HandeiaUser;
|
|
39
|
+
permissions: string[];
|
|
40
|
+
trigger: 'user_action' | 'haia_invoke' | 'schedule';
|
|
41
|
+
/** Surface HAIA wants to render. */
|
|
42
|
+
surface: Surface;
|
|
43
|
+
query?: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
interface GandiaJWTClaims {
|
|
46
|
+
sub: string;
|
|
47
|
+
tenant_id: string;
|
|
48
|
+
email?: string | undefined;
|
|
49
|
+
role?: string | undefined;
|
|
50
|
+
permissions: string[];
|
|
51
|
+
iat: number;
|
|
52
|
+
exp: number;
|
|
53
|
+
}
|
|
54
|
+
interface HandeiaJWTClaims {
|
|
55
|
+
sub: string;
|
|
56
|
+
email?: string | undefined;
|
|
57
|
+
name?: string | undefined;
|
|
58
|
+
permissions: string[];
|
|
59
|
+
iat: number;
|
|
60
|
+
exp: number;
|
|
61
|
+
}
|
|
62
|
+
interface AuditRecord {
|
|
63
|
+
data_sources?: string[] | undefined;
|
|
64
|
+
records_accessed?: number | undefined;
|
|
65
|
+
[key: string]: unknown;
|
|
66
|
+
}
|
|
67
|
+
interface RespondOpts {
|
|
68
|
+
call_id?: string | undefined;
|
|
69
|
+
audit?: AuditRecord | undefined;
|
|
70
|
+
}
|
|
71
|
+
interface CardPayload {
|
|
72
|
+
title: string;
|
|
73
|
+
value?: string | number | undefined;
|
|
74
|
+
unit?: string | undefined;
|
|
75
|
+
trend?: 'up' | 'down' | 'neutral' | undefined;
|
|
76
|
+
icon?: string | undefined;
|
|
77
|
+
subtitle?: string | undefined;
|
|
78
|
+
color?: string | undefined;
|
|
79
|
+
[key: string]: unknown;
|
|
80
|
+
}
|
|
81
|
+
interface TablePayload {
|
|
82
|
+
columns: string[] | Array<{
|
|
83
|
+
key: string;
|
|
84
|
+
label: string;
|
|
85
|
+
type?: string | undefined;
|
|
86
|
+
}>;
|
|
87
|
+
rows: Array<Record<string, unknown>>;
|
|
88
|
+
total?: number | undefined;
|
|
89
|
+
page?: number | undefined;
|
|
90
|
+
per_page?: number | undefined;
|
|
91
|
+
}
|
|
92
|
+
interface WidgetPayload {
|
|
93
|
+
url: string;
|
|
94
|
+
height?: number | string | undefined;
|
|
95
|
+
width?: number | string | undefined;
|
|
96
|
+
meta?: Record<string, unknown> | undefined;
|
|
97
|
+
}
|
|
98
|
+
interface ActionPayload {
|
|
99
|
+
type: string;
|
|
100
|
+
label?: string | undefined;
|
|
101
|
+
params?: Record<string, unknown> | undefined;
|
|
102
|
+
confirm?: boolean | undefined;
|
|
103
|
+
destructive?: boolean | undefined;
|
|
104
|
+
}
|
|
105
|
+
interface BaseVAIAResponse {
|
|
106
|
+
ok: true;
|
|
107
|
+
call_id?: string | undefined;
|
|
108
|
+
audit?: AuditRecord | undefined;
|
|
109
|
+
}
|
|
110
|
+
type CardResponse = BaseVAIAResponse & {
|
|
111
|
+
output_type: 'card';
|
|
112
|
+
data: CardPayload;
|
|
113
|
+
};
|
|
114
|
+
type TableResponse = BaseVAIAResponse & {
|
|
115
|
+
output_type: 'table';
|
|
116
|
+
data: TablePayload;
|
|
117
|
+
};
|
|
118
|
+
type TextResponse = BaseVAIAResponse & {
|
|
119
|
+
output_type: 'text';
|
|
120
|
+
text: string;
|
|
121
|
+
markdown?: boolean | undefined;
|
|
122
|
+
};
|
|
123
|
+
type WidgetResponse = BaseVAIAResponse & {
|
|
124
|
+
output_type: 'widget';
|
|
125
|
+
data: WidgetPayload;
|
|
126
|
+
};
|
|
127
|
+
type ActionResponse = BaseVAIAResponse & {
|
|
128
|
+
output_type: 'action';
|
|
129
|
+
data: ActionPayload;
|
|
130
|
+
};
|
|
131
|
+
type DataResponse = BaseVAIAResponse & {
|
|
132
|
+
output_type: 'data';
|
|
133
|
+
data: Record<string, unknown>;
|
|
134
|
+
};
|
|
135
|
+
type ErrorResponse = {
|
|
136
|
+
ok: false;
|
|
137
|
+
error: string;
|
|
138
|
+
code?: string | undefined;
|
|
139
|
+
};
|
|
140
|
+
type VAIAResponse = CardResponse | TableResponse | TextResponse | WidgetResponse | ActionResponse | DataResponse;
|
|
141
|
+
type SurfaceHandlers = Partial<{
|
|
142
|
+
card: () => CardPayload | Promise<CardPayload>;
|
|
143
|
+
table: () => TablePayload | Promise<TablePayload>;
|
|
144
|
+
text: () => string | Promise<string>;
|
|
145
|
+
widget: () => WidgetPayload | Promise<WidgetPayload>;
|
|
146
|
+
action: () => ActionPayload | Promise<ActionPayload>;
|
|
147
|
+
data: () => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
148
|
+
}>;
|
|
149
|
+
interface SurfaceConfig {
|
|
150
|
+
endpoint: string;
|
|
151
|
+
description?: string | undefined;
|
|
152
|
+
}
|
|
153
|
+
interface CapabilityConfig {
|
|
154
|
+
/** Unique capability ID — reverse domain: 'mx.mi-capacidad' */
|
|
155
|
+
id: string;
|
|
156
|
+
name: string;
|
|
157
|
+
version: string;
|
|
158
|
+
/** Which VAIA platform(s) this capability targets. */
|
|
159
|
+
target: EcoTarget;
|
|
160
|
+
type: PublishType;
|
|
161
|
+
level?: 'widget' | 'artefacto' | 'espacio' | undefined;
|
|
162
|
+
sector: string;
|
|
163
|
+
/** Which surfaces the capability can respond to, and their invoke endpoint. */
|
|
164
|
+
surfaces: Partial<Record<Surface, SurfaceConfig>>;
|
|
165
|
+
permissions: string[];
|
|
166
|
+
risk: Risk;
|
|
167
|
+
description?: string | undefined;
|
|
168
|
+
tags?: string[] | undefined;
|
|
169
|
+
/** Set to true if your app has its own login (triggers JWT bypass flow). */
|
|
170
|
+
has_own_auth?: boolean | undefined;
|
|
171
|
+
stores_data?: boolean | undefined;
|
|
172
|
+
trains_models?: boolean | undefined;
|
|
173
|
+
requires_consent?: boolean | undefined;
|
|
174
|
+
}
|
|
175
|
+
declare class VAIAError extends Error {
|
|
176
|
+
readonly code: string;
|
|
177
|
+
readonly status: number;
|
|
178
|
+
constructor(message: string, code: string, status?: number);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* gandia.verify — verifies an incoming invoke call from Gandia-7.
|
|
183
|
+
*
|
|
184
|
+
* Checks:
|
|
185
|
+
* 1. X-Gandia-Signature (HMAC-SHA256 over timestamp + "." + raw body)
|
|
186
|
+
* 2. X-Gandia-Timestamp within ±5 minutes (replay attack prevention)
|
|
187
|
+
* 3. Parses and types the body as GandiaContext
|
|
188
|
+
*
|
|
189
|
+
* Usage:
|
|
190
|
+
* const { ctx } = await verify(request, process.env.GANDIA_KEY_SECRET!)
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
/** Raw body of the invoke call. Returned alongside ctx so you don't re-read the stream. */
|
|
194
|
+
interface VerifyResult {
|
|
195
|
+
ctx: GandiaContext;
|
|
196
|
+
raw: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Call at the top of your `/api/gandia/invoke` route handler.
|
|
200
|
+
* Throws VAIAError if the signature is invalid or the timestamp is stale.
|
|
201
|
+
*/
|
|
202
|
+
declare function verify$3(request: Request, secret: string): Promise<VerifyResult>;
|
|
203
|
+
/** Quick check — use before calling verify() if you want to short-circuit probes. */
|
|
204
|
+
declare function isProbe$1(request: Request): boolean;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* gandia.jwt — JWT helpers for iframe auth bypass.
|
|
208
|
+
*
|
|
209
|
+
* When Gandia-7 opens a developer's app as an iframe, it appends:
|
|
210
|
+
* ?gandia_token=<signed_jwt>
|
|
211
|
+
*
|
|
212
|
+
* The developer verifies the token, extracts the user/tenant claims,
|
|
213
|
+
* and creates a session — skipping their own login page.
|
|
214
|
+
*
|
|
215
|
+
* Usage (server-side):
|
|
216
|
+
* const claims = await gandia.jwt.verify(token, process.env.GANDIA_KEY_SECRET!)
|
|
217
|
+
* // → { sub, tenant_id, email, role, permissions, exp, iat }
|
|
218
|
+
*
|
|
219
|
+
* Usage (VAIA-side, when generating tokens for developer iframes):
|
|
220
|
+
* const token = await gandia.jwt.sign({ sub: userId, tenant_id, ... }, secret, { expiresIn: 3600 })
|
|
221
|
+
*/
|
|
222
|
+
|
|
223
|
+
interface GandiaJWTSignInput {
|
|
224
|
+
sub: string;
|
|
225
|
+
tenant_id: string;
|
|
226
|
+
email?: string | undefined;
|
|
227
|
+
role?: string | undefined;
|
|
228
|
+
permissions?: string[] | undefined;
|
|
229
|
+
}
|
|
230
|
+
interface SignOpts$1 {
|
|
231
|
+
/** Seconds until expiry. Default: 3600 (1 hour). */
|
|
232
|
+
expiresIn?: number | undefined;
|
|
233
|
+
}
|
|
234
|
+
/** Signs a new Gandia iframe JWT. Typically called by Gandia-7, not by the developer. */
|
|
235
|
+
declare function sign$1(input: GandiaJWTSignInput, secret: string, opts?: SignOpts$1): Promise<string>;
|
|
236
|
+
/** Verifies a Gandia iframe JWT and returns its claims. Throws VAIAError on failure. */
|
|
237
|
+
declare function verify$2(token: string, secret: string): Promise<GandiaJWTClaims>;
|
|
238
|
+
/**
|
|
239
|
+
* Extracts `gandia_token` from a URL and verifies it.
|
|
240
|
+
* Convenience for iframe entry-point routes.
|
|
241
|
+
*
|
|
242
|
+
* const claims = await gandia.jwt.fromUrl(request.url, secret)
|
|
243
|
+
*/
|
|
244
|
+
declare function fromUrl$1(url: string | URL, secret: string): Promise<GandiaJWTClaims>;
|
|
245
|
+
|
|
246
|
+
type jwt$1_GandiaJWTSignInput = GandiaJWTSignInput;
|
|
247
|
+
declare namespace jwt$1 {
|
|
248
|
+
export { type jwt$1_GandiaJWTSignInput as GandiaJWTSignInput, type SignOpts$1 as SignOpts, fromUrl$1 as fromUrl, sign$1 as sign, verify$2 as verify };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* gandia.respond — typed response builders.
|
|
253
|
+
*
|
|
254
|
+
* Each method returns a Web API Response with the correct VAIA envelope.
|
|
255
|
+
* HAIA reads `output_type` to decide how to render the result.
|
|
256
|
+
*
|
|
257
|
+
* For non-Response frameworks (Express, Fastify), use gandia.make.* instead.
|
|
258
|
+
*
|
|
259
|
+
* Usage:
|
|
260
|
+
* // Returns Web API Response
|
|
261
|
+
* return gandia.respond.card({ title: 'Riesgo', value: 72, unit: '%' })
|
|
262
|
+
*
|
|
263
|
+
* // Multi-surface: GAIA tells you which surface it wants via ctx.surface
|
|
264
|
+
* return gandia.respond.surface(ctx.surface, {
|
|
265
|
+
* card: () => ({ title: 'Riesgo', value: 72 }),
|
|
266
|
+
* table: () => ({ columns: ['alumno', 'score'], rows }),
|
|
267
|
+
* text: () => `El riesgo del grupo es ${risk}%`,
|
|
268
|
+
* })
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
declare const make: {
|
|
272
|
+
readonly card: (payload: CardPayload, opts?: RespondOpts) => CardResponse;
|
|
273
|
+
readonly table: (payload: TablePayload, opts?: RespondOpts) => TableResponse;
|
|
274
|
+
readonly text: (content: string, opts?: RespondOpts & {
|
|
275
|
+
markdown?: boolean;
|
|
276
|
+
}) => TextResponse;
|
|
277
|
+
readonly widget: (payload: WidgetPayload, opts?: RespondOpts) => WidgetResponse;
|
|
278
|
+
readonly action: (payload: ActionPayload, opts?: RespondOpts) => ActionResponse;
|
|
279
|
+
readonly data: (payload: Record<string, unknown>, opts?: RespondOpts) => DataResponse;
|
|
280
|
+
};
|
|
281
|
+
declare const respond: {
|
|
282
|
+
/** A compact card: title, value, unit, trend, etc. */
|
|
283
|
+
readonly card: (payload: CardPayload, opts?: RespondOpts) => Response;
|
|
284
|
+
/** Tabular data with columns + rows. */
|
|
285
|
+
readonly table: (payload: TablePayload, opts?: RespondOpts) => Response;
|
|
286
|
+
/** Plain text or markdown — shown in chat or narrative views. */
|
|
287
|
+
readonly text: (content: string, opts?: RespondOpts & {
|
|
288
|
+
markdown?: boolean;
|
|
289
|
+
}) => Response;
|
|
290
|
+
/** An iframe pointing to the developer's own UI. */
|
|
291
|
+
readonly widget: (payload: WidgetPayload, opts?: RespondOpts) => Response;
|
|
292
|
+
/** Trigger an action (mutation, navigation, confirm dialog). */
|
|
293
|
+
readonly action: (payload: ActionPayload, opts?: RespondOpts) => Response;
|
|
294
|
+
/** Arbitrary JSON — HAIA decides how to render based on shape. */
|
|
295
|
+
readonly data: (payload: Record<string, unknown>, opts?: RespondOpts) => Response;
|
|
296
|
+
/** Simple 200 OK — useful for probe responses. */
|
|
297
|
+
readonly ok: (opts?: RespondOpts) => Response;
|
|
298
|
+
/** Returns a 4xx/5xx error response. */
|
|
299
|
+
readonly error: (message: string, status?: number, code?: string) => Response;
|
|
300
|
+
/**
|
|
301
|
+
* Multi-surface responder.
|
|
302
|
+
* GAIA sends `ctx.surface` telling you what to render.
|
|
303
|
+
* Map each surface to its handler and this picks the right one.
|
|
304
|
+
*
|
|
305
|
+
* return gandia.respond.surface(ctx.surface, {
|
|
306
|
+
* card: () => ({ title: 'Riesgo', value: 72, unit: '%' }),
|
|
307
|
+
* table: () => ({ columns: [...], rows: [...] }),
|
|
308
|
+
* text: () => `El riesgo es 72%`,
|
|
309
|
+
* }, opts)
|
|
310
|
+
*/
|
|
311
|
+
readonly surface: (surface: Surface, handlers: SurfaceHandlers, opts?: RespondOpts) => Promise<Response>;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* gandia.can / gandia.require — permission helpers.
|
|
316
|
+
*
|
|
317
|
+
* Usage:
|
|
318
|
+
* if (!gandia.can(ctx, 'read:students')) return gandia.respond.error('Forbidden', 403)
|
|
319
|
+
* gandia.require(ctx, 'write:alerts') // throws VAIAError 403 if missing
|
|
320
|
+
*
|
|
321
|
+
* Supports wildcard scopes:
|
|
322
|
+
* 'read:*' — matches all read permissions
|
|
323
|
+
* 'read:students' — exact match
|
|
324
|
+
*/
|
|
325
|
+
|
|
326
|
+
/** Returns true if the context has the given permission. */
|
|
327
|
+
declare function can(ctx: Pick<GandiaContext, 'permissions'>, permission: string): boolean;
|
|
328
|
+
/** Returns true if the context has ALL listed permissions. */
|
|
329
|
+
declare function canAll(ctx: Pick<GandiaContext, 'permissions'>, ...permissions: string[]): boolean;
|
|
330
|
+
/** Returns true if the context has ANY of the listed permissions. */
|
|
331
|
+
declare function canAny(ctx: Pick<GandiaContext, 'permissions'>, ...permissions: string[]): boolean;
|
|
332
|
+
/** Throws VAIAError 403 if the context does NOT have the given permission. */
|
|
333
|
+
declare function require$1(ctx: Pick<GandiaContext, 'permissions'>, permission: string): void;
|
|
334
|
+
/** Throws VAIAError 403 if the context does NOT have ALL listed permissions. */
|
|
335
|
+
declare function requireAll(ctx: Pick<GandiaContext, 'permissions'>, ...permissions: string[]): void;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* gandia — integration namespace for Gandia-7 (institutional platform).
|
|
339
|
+
*
|
|
340
|
+
* Quick start:
|
|
341
|
+
* import { gandia } from '@vaia/sdk'
|
|
342
|
+
*
|
|
343
|
+
* export async function POST(req: Request) {
|
|
344
|
+
* try {
|
|
345
|
+
* const { ctx } = await gandia.verify(req, process.env.GANDIA_KEY_SECRET!)
|
|
346
|
+
* gandia.require(ctx, 'read:students')
|
|
347
|
+
* const data = await myDb.getStudents(ctx.tenant.id)
|
|
348
|
+
* return gandia.respond.surface(ctx.surface, {
|
|
349
|
+
* card: () => ({ title: 'Total alumnos', value: data.length }),
|
|
350
|
+
* table: () => ({ columns: ['nombre', 'riesgo'], rows: data }),
|
|
351
|
+
* text: () => `${data.length} alumnos en ${ctx.tenant.name}`,
|
|
352
|
+
* })
|
|
353
|
+
* } catch (err) {
|
|
354
|
+
* if (err instanceof VAIAError) return gandia.respond.error(err.message, err.status)
|
|
355
|
+
* throw err
|
|
356
|
+
* }
|
|
357
|
+
* }
|
|
358
|
+
*/
|
|
359
|
+
|
|
360
|
+
type _gandia_VerifyResult = VerifyResult;
|
|
361
|
+
declare const _gandia_can: typeof can;
|
|
362
|
+
declare const _gandia_canAll: typeof canAll;
|
|
363
|
+
declare const _gandia_canAny: typeof canAny;
|
|
364
|
+
declare const _gandia_make: typeof make;
|
|
365
|
+
declare const _gandia_requireAll: typeof requireAll;
|
|
366
|
+
declare const _gandia_respond: typeof respond;
|
|
367
|
+
declare namespace _gandia {
|
|
368
|
+
export { type _gandia_VerifyResult as VerifyResult, _gandia_can as can, _gandia_canAll as canAll, _gandia_canAny as canAny, isProbe$1 as isProbe, jwt$1 as jwt, _gandia_make as make, require$1 as require, _gandia_requireAll as requireAll, _gandia_respond as respond, verify$3 as verify };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* handeia.verify — verifies an incoming invoke call from Handeia.
|
|
373
|
+
* Same HMAC protocol as gandia.verify but with Handeia-specific headers
|
|
374
|
+
* and a HandeiaContext (user personal, no tenant).
|
|
375
|
+
*/
|
|
376
|
+
|
|
377
|
+
interface HandeiaVerifyResult {
|
|
378
|
+
ctx: HandeiaContext;
|
|
379
|
+
raw: string;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Call at the top of your `/api/handeia/invoke` route handler.
|
|
383
|
+
* Throws VAIAError if the signature is invalid or the timestamp is stale.
|
|
384
|
+
*/
|
|
385
|
+
declare function verify$1(request: Request, secret: string): Promise<HandeiaVerifyResult>;
|
|
386
|
+
declare function isProbe(request: Request): boolean;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* handeia.jwt — JWT helpers for Handeia iframe auth bypass.
|
|
390
|
+
* Same pattern as gandia.jwt but for personal context (no tenant).
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
interface HandeiaJWTSignInput {
|
|
394
|
+
sub: string;
|
|
395
|
+
email?: string | undefined;
|
|
396
|
+
name?: string | undefined;
|
|
397
|
+
permissions?: string[] | undefined;
|
|
398
|
+
}
|
|
399
|
+
interface SignOpts {
|
|
400
|
+
expiresIn?: number | undefined;
|
|
401
|
+
}
|
|
402
|
+
declare function sign(input: HandeiaJWTSignInput, secret: string, opts?: SignOpts): Promise<string>;
|
|
403
|
+
declare function verify(token: string, secret: string): Promise<HandeiaJWTClaims>;
|
|
404
|
+
/** Extracts and verifies `handeia_token` from a URL. */
|
|
405
|
+
declare function fromUrl(url: string | URL, secret: string): Promise<HandeiaJWTClaims>;
|
|
406
|
+
|
|
407
|
+
type jwt_HandeiaJWTSignInput = HandeiaJWTSignInput;
|
|
408
|
+
type jwt_SignOpts = SignOpts;
|
|
409
|
+
declare const jwt_fromUrl: typeof fromUrl;
|
|
410
|
+
declare const jwt_sign: typeof sign;
|
|
411
|
+
declare const jwt_verify: typeof verify;
|
|
412
|
+
declare namespace jwt {
|
|
413
|
+
export { type jwt_HandeiaJWTSignInput as HandeiaJWTSignInput, type jwt_SignOpts as SignOpts, jwt_fromUrl as fromUrl, jwt_sign as sign, jwt_verify as verify };
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* handeia — integration namespace for Handeia (personal platform).
|
|
418
|
+
*
|
|
419
|
+
* Quick start:
|
|
420
|
+
* import { handeia } from '@vaia/sdk'
|
|
421
|
+
*
|
|
422
|
+
* export async function POST(req: Request) {
|
|
423
|
+
* try {
|
|
424
|
+
* const { ctx } = await handeia.verify(req, process.env.HANDEIA_KEY_SECRET!)
|
|
425
|
+
* const profile = await myDb.getProfile(ctx.user.id)
|
|
426
|
+
* return handeia.respond.surface(ctx.surface, {
|
|
427
|
+
* card: () => ({ title: profile.name, subtitle: profile.role }),
|
|
428
|
+
* text: () => `Hola ${profile.name}`,
|
|
429
|
+
* })
|
|
430
|
+
* } catch (err) {
|
|
431
|
+
* if (err instanceof VAIAError) return handeia.respond.error(err.message, err.status)
|
|
432
|
+
* throw err
|
|
433
|
+
* }
|
|
434
|
+
* }
|
|
435
|
+
*/
|
|
436
|
+
|
|
437
|
+
type _handeia_HandeiaVerifyResult = HandeiaVerifyResult;
|
|
438
|
+
declare const _handeia_can: typeof can;
|
|
439
|
+
declare const _handeia_canAll: typeof canAll;
|
|
440
|
+
declare const _handeia_canAny: typeof canAny;
|
|
441
|
+
declare const _handeia_isProbe: typeof isProbe;
|
|
442
|
+
declare const _handeia_jwt: typeof jwt;
|
|
443
|
+
declare const _handeia_make: typeof make;
|
|
444
|
+
declare const _handeia_requireAll: typeof requireAll;
|
|
445
|
+
declare const _handeia_respond: typeof respond;
|
|
446
|
+
declare namespace _handeia {
|
|
447
|
+
export { type _handeia_HandeiaVerifyResult as HandeiaVerifyResult, _handeia_can as can, _handeia_canAll as canAll, _handeia_canAny as canAny, _handeia_isProbe as isProbe, _handeia_jwt as jwt, _handeia_make as make, require$1 as require, _handeia_requireAll as requireAll, _handeia_respond as respond, verify$1 as verify };
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* defineCapability — declares a VAIA capability in code.
|
|
452
|
+
*
|
|
453
|
+
* This is both a type-safety layer (catches config errors at compile time)
|
|
454
|
+
* and the source of truth for `npx vaia manifest` (generates gandia.manifest.json).
|
|
455
|
+
*
|
|
456
|
+
* The Shazam engine detects `defineCapability` in your code and reads the
|
|
457
|
+
* config with 100% confidence — no manual confirmation needed in the portal.
|
|
458
|
+
*
|
|
459
|
+
* Usage (vaia.config.ts in project root):
|
|
460
|
+
* import { defineCapability } from '@vaia/sdk'
|
|
461
|
+
*
|
|
462
|
+
* export default defineCapability({
|
|
463
|
+
* id: 'mx.monitor-riesgo-academico',
|
|
464
|
+
* name: 'Monitor de Riesgo Académico',
|
|
465
|
+
* version: '1.0.0',
|
|
466
|
+
* target: 'gandia',
|
|
467
|
+
* type: 'app',
|
|
468
|
+
* level: 'artefacto',
|
|
469
|
+
* sector: 'educacion',
|
|
470
|
+
* surfaces: {
|
|
471
|
+
* card: { endpoint: '/api/gandia/invoke' },
|
|
472
|
+
* table: { endpoint: '/api/gandia/invoke' },
|
|
473
|
+
* text: { endpoint: '/api/gandia/invoke' },
|
|
474
|
+
* },
|
|
475
|
+
* permissions: ['read:students', 'read:grades', 'write:alerts'],
|
|
476
|
+
* risk: 'medium',
|
|
477
|
+
* })
|
|
478
|
+
*/
|
|
479
|
+
|
|
480
|
+
interface VAIAManifest {
|
|
481
|
+
schema: '1.0';
|
|
482
|
+
capability_id: string;
|
|
483
|
+
name: string;
|
|
484
|
+
version: string;
|
|
485
|
+
target: EcoTarget | EcoTarget[];
|
|
486
|
+
type: string;
|
|
487
|
+
level?: string | undefined;
|
|
488
|
+
sector: string;
|
|
489
|
+
surfaces: string[];
|
|
490
|
+
permissions: string[];
|
|
491
|
+
risk: Risk;
|
|
492
|
+
has_own_auth: boolean;
|
|
493
|
+
stores_data: boolean;
|
|
494
|
+
trains_models: boolean;
|
|
495
|
+
requires_consent: boolean;
|
|
496
|
+
description?: string | undefined;
|
|
497
|
+
tags?: string[] | undefined;
|
|
498
|
+
linked: boolean;
|
|
499
|
+
generated_by: '@vaia/sdk';
|
|
500
|
+
generated_at: string;
|
|
501
|
+
}
|
|
502
|
+
/** Validates and returns the capability config. Throws if required fields are missing. */
|
|
503
|
+
declare function defineCapability(config: CapabilityConfig): CapabilityConfig;
|
|
504
|
+
/** Converts a CapabilityConfig to a gandia.manifest.json object. */
|
|
505
|
+
declare function toManifest(config: CapabilityConfig): VAIAManifest;
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* @vaia/sdk — VAIA Platform Integration SDK
|
|
509
|
+
*
|
|
510
|
+
* Provides two namespaces:
|
|
511
|
+
* gandia → Gandia-7 (institutional platform)
|
|
512
|
+
* handeia → Handeia (personal platform)
|
|
513
|
+
*
|
|
514
|
+
* Quick start:
|
|
515
|
+
* import { gandia, handeia, defineCapability, VAIAError } from '@vaia/sdk'
|
|
516
|
+
*/
|
|
517
|
+
|
|
518
|
+
declare const gandia: typeof _gandia;
|
|
519
|
+
declare const handeia: typeof _handeia;
|
|
520
|
+
|
|
521
|
+
export { type ActionPayload, type ActionResponse, type AuditRecord, type CapabilityConfig, type CardPayload, type CardResponse, type DataResponse, type EcoTarget, type ErrorResponse, type GandiaContext, type GandiaJWTClaims, type GandiaTenant, type GandiaUser, type HandeiaContext, type HandeiaJWTClaims, type HandeiaUser, type NodeType, type OutputType, type PublishType, type RespondOpts, type Risk, type Surface, type SurfaceHandlers, type TablePayload, type TableResponse, type TextResponse, VAIAError, type VAIAManifest, type VAIAResponse, type WidgetPayload, type WidgetResponse, defineCapability, gandia, handeia, toManifest };
|