โ† Back to list
skillrecordings

sdk-adapter

by skillrecordings

๐Ÿค– an AI agent for the support desk at Badass Courses

โญ 0๐Ÿด 0๐Ÿ“… Jan 25, 2026

SKILL.md


name: sdk-adapter description: Create SDK adapters for new app integrations. Use when onboarding a new Skill Recordings product, implementing the SupportIntegration interface, or scaffolding a new app. allowed-tools: Read, Grep, Glob, Edit, Write, Bash

SDK + Adapter Pattern

Adding a new app should be "a skill init away". Each app implements the SupportIntegration interface.

Architecture Overview

Support Platform                          App Integration
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Agent Tool      โ”‚  HTTPS + HMAC-SHA256 โ”‚ createSupport-  โ”‚
โ”‚ (lookupUser,    โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚ Handler         โ”‚
โ”‚  processRefund) โ”‚  x-signature header  โ”‚ (verifies sig)  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚                                        โ”‚
         โ–ผ                                        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ IntegrationClientโ”‚                     โ”‚ SupportIntegration
โ”‚ (signs requests) โ”‚                     โ”‚ (your impl)     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

SupportIntegration Interface

Import from @skillrecordings/sdk/integration:

import type { SupportIntegration } from '@skillrecordings/sdk/integration'

export interface SupportIntegration {
  // Required: User lookup
  lookupUser(email: string): Promise<User | null>
  getPurchases(userId: string): Promise<Purchase[]>

  // Optional: Subscriptions
  getSubscriptions?(userId: string): Promise<Subscription[]>

  // Required: Access management
  revokeAccess(params: {
    purchaseId: string
    reason: string
    refundId: string
  }): Promise<ActionResult>

  transferPurchase(params: {
    purchaseId: string
    fromUserId: string
    toEmail: string
  }): Promise<ActionResult>

  // Required: Auth
  generateMagicLink(params: {
    email: string
    expiresIn: number
  }): Promise<{ url: string }>

  // Optional: Profile updates
  updateEmail?(params: { userId: string; newEmail: string }): Promise<ActionResult>
  updateName?(params: { userId: string; newName: string }): Promise<ActionResult>

  // Optional: Team features
  getClaimedSeats?(bulkCouponId: string): Promise<ClaimedSeat[]>
}

Type Definitions

Import from @skillrecordings/sdk/types:

export interface User {
  id: string
  email: string
  name?: string
  createdAt?: Date
}

export interface Purchase {
  id: string
  userId: string
  productId: string
  productName?: string
  purchasedAt: Date
  amount: number
  currency?: string
  stripeChargeId?: string
  status: 'active' | 'refunded' | 'transferred'
}

export interface Subscription {
  id: string
  userId: string
  productId: string
  status: 'active' | 'canceled' | 'past_due' | 'trialing'
  currentPeriodEnd: Date
  cancelAtPeriodEnd: boolean
}

export interface ActionResult {
  success: boolean
  message?: string
}

HMAC Signature Verification

Requests from the support platform include an x-signature header:

x-signature: timestamp=1737163200,v1=<hex_signature>

Payload to sign: ${timestamp}.${JSON.stringify(body)}

The handler verifies:

  1. Signature matches HMAC-SHA256(payload, webhook_secret)
  2. Timestamp is within 5 minutes (replay protection)

Next.js Route Handler

// app/api/support/route.ts
import { createSupportHandler } from '@skillrecordings/sdk/handler'
import type { SupportIntegration } from '@skillrecordings/sdk/integration'

const integration: SupportIntegration = {
  async lookupUser(email) {
    return db.user.findUnique({ where: { email } })
  },
  async getPurchases(userId) {
    return db.purchase.findMany({ where: { userId } })
  },
  async revokeAccess({ purchaseId, reason, refundId }) {
    await db.purchase.update({
      where: { id: purchaseId },
      data: { status: 'refunded', refundReason: reason, stripeRefundId: refundId }
    })
    return { success: true }
  },
  async transferPurchase({ purchaseId, fromUserId, toEmail }) {
    const toUser = await db.user.findUnique({ where: { email: toEmail } })
    await db.purchase.update({
      where: { id: purchaseId },
      data: { userId: toUser.id, status: 'transferred' }
    })
    return { success: true }
  },
  async generateMagicLink({ email, expiresIn }) {
    const token = await createMagicToken(email, expiresIn)
    return { url: `${APP_URL}/auth/magic?token=${token}` }
  },
}

// Create handler - handles signature verification automatically
const handler = createSupportHandler(integration, {
  webhookSecret: process.env.SUPPORT_WEBHOOK_SECRET!,
})

export async function POST(request: Request) {
  return handler(request)
}

App Registration

Each app needs an entry in the apps table:

{
  slug: 'total-typescript',
  name: 'Total TypeScript',
  front_inbox_id: 'inb_xxx',
  stripe_account_id: 'acct_xxx',
  integration_base_url: 'https://totaltypescript.com/api/support',
  webhook_secret: 'whsec_xxx',  // Shared secret for HMAC signing
  capabilities: ['refund', 'transfer', 'magic_link'],
  auto_approve_refund_days: 30,
  auto_approve_transfer_days: 14,
  escalation_slack_channel: 'C0XXXXXXX',
}

File Locations

FilePurpose
packages/sdk/src/types.tsUser, Purchase, Subscription, ActionResult types
packages/sdk/src/integration.tsSupportIntegration interface
packages/sdk/src/handler.tscreateSupportHandler factory
packages/sdk/src/client.tsIntegrationClient (used by core)
packages/core/src/services/app-registry.tsApp config lookup with 5-min TTL cache

Package Exports

// Types
import type { User, Purchase, ActionResult } from '@skillrecordings/sdk/types'

// Interface
import type { SupportIntegration } from '@skillrecordings/sdk/integration'

// Handler (for app implementations)
import { createSupportHandler } from '@skillrecordings/sdk/handler'

// Client (used internally by core)
import { IntegrationClient } from '@skillrecordings/sdk/client'

Reference Docs

For full details, see:

  • docs/support-app-prd/67-sdk.md
  • docs/ARCHITECTURE.md (SDK Integration Flow section)

Score

Total Score

50/100

Based on repository quality metrics

โœ“SKILL.md

SKILL.mdใƒ•ใ‚กใ‚คใƒซใŒๅซใพใ‚Œใฆใ„ใ‚‹

+20
โ—‹LICENSE

ใƒฉใ‚คใ‚ปใƒณใ‚นใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹

0/10
โ—‹่ชฌๆ˜Žๆ–‡

100ๆ–‡ๅญ—ไปฅไธŠใฎ่ชฌๆ˜ŽใŒใ‚ใ‚‹

0/10
โ—‹ไบบๆฐ—

GitHub Stars 100ไปฅไธŠ

0/15
โ—‹ๆœ€่ฟ‘ใฎๆดปๅ‹•

3ใƒถๆœˆไปฅๅ†…ใซๆ›ดๆ–ฐใŒใ‚ใ‚‹

0/10
โ—‹ใƒ•ใ‚ฉใƒผใ‚ฏ

10ๅ›žไปฅไธŠใƒ•ใ‚ฉใƒผใ‚ฏใ•ใ‚Œใฆใ„ใ‚‹

0/5
โœ“Issue็ฎก็†

ใ‚ชใƒผใƒ—ใƒณIssueใŒ50ๆœชๆบ€

+5
โœ“่จ€่ชž

ใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐ่จ€่ชžใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹

+5
โ—‹ใ‚ฟใ‚ฐ

1ใคไปฅไธŠใฎใ‚ฟใ‚ฐใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹

0/5

Reviews

๐Ÿ’ฌ

Reviews coming soon