import { z } from "zod"; import { buildChannelConfigSchema } from "clawdbot/plugin-sdk"; const allowFromEntry = z.union([z.string(), z.number()]); /** * Validates https:// URLs only (no javascript:, data:, file:, etc.) */ const safeUrlSchema = z .string() .url() .refine( (url) => { try { const parsed = new URL(url); return parsed.protocol === "https:"; } catch { return false; } }, { message: "URL must use https:// protocol" } ); /** * NIP-01 profile metadata schema * https://github.com/nostr-protocol/nips/blob/master/01.md */ export const NostrProfileSchema = z.object({ /** Username (NIP-01: name) - max 256 chars */ name: z.string().max(256).optional(), /** Display name (NIP-01: display_name) - max 256 chars */ displayName: z.string().max(256).optional(), /** Bio/description (NIP-01: about) - max 2000 chars */ about: z.string().max(2000).optional(), /** Profile picture URL (must be https) */ picture: safeUrlSchema.optional(), /** Banner image URL (must be https) */ banner: safeUrlSchema.optional(), /** Website URL (must be https) */ website: safeUrlSchema.optional(), /** NIP-05 identifier (e.g., "user@example.com") */ nip05: z.string().optional(), /** Lightning address (LUD-16) */ lud16: z.string().optional(), }); export type NostrProfile = z.infer; /** * Zod schema for channels.nostr.* configuration */ export const NostrConfigSchema = z.object({ /** Account name (optional display name) */ name: z.string().optional(), /** Whether this channel is enabled */ enabled: z.boolean().optional(), /** Private key in hex or nsec bech32 format */ privateKey: z.string().optional(), /** WebSocket relay URLs to connect to */ relays: z.array(z.string()).optional(), /** DM access policy: pairing, allowlist, open, or disabled */ dmPolicy: z.enum(["pairing", "allowlist", "open", "disabled"]).optional(), /** Allowed sender pubkeys (npub or hex format) */ allowFrom: z.array(allowFromEntry).optional(), /** Profile metadata (NIP-01 kind:0 content) */ profile: NostrProfileSchema.optional(), }); export type NostrConfig = z.infer; /** * JSON Schema for Control UI (converted from Zod) */ export const nostrChannelConfigSchema = buildChannelConfigSchema(NostrConfigSchema);