UNPKG

@chittyos/core

Version:

ChittyOS Core - Essential package with ID, auth, verification, beacon tracking, and brand components for all ChittyOS applications

1,722 lines (1,694 loc) 49.2 kB
var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; // src/beacon/index.ts var beacon_exports = {}; __export(beacon_exports, { configure: () => configure, detectApp: () => detectApp, init: () => init, sendBeacon: () => sendBeacon, stop: () => stop }); import { nanoid } from "nanoid"; import * as os from "os"; import * as fs from "fs"; import { execSync } from "child_process"; var DEFAULT_CONFIG = { endpoint: process.env.CHITTY_BEACON_ENDPOINT || "https://beacon.chitty.cc", interval: parseInt(process.env.CHITTY_BEACON_INTERVAL || "") || 3e5, enabled: process.env.CHITTY_BEACON_DISABLED !== "true", silent: process.env.CHITTY_BEACON_VERBOSE !== "true" }; var config = { ...DEFAULT_CONFIG }; var appInfo = null; var heartbeatInterval = null; function configure(customConfig) { config = { ...config, ...customConfig }; } function detectApp() { const app = { id: generateAppId(), name: detectAppName(), version: detectVersion(), platform: detectPlatform(), environment: process.env.NODE_ENV || "production", hostname: os.hostname(), nodeVersion: process.version, os: `${os.type()} ${os.release()}`, hasClaudeCode: detectClaudeCode(), hasGit: fs.existsSync(".git"), startedAt: (/* @__PURE__ */ new Date()).toISOString(), pid: process.pid, chittyos: { core: "1.0.0", modules: detectChittyModules() } }; if (app.hasGit) { try { app.git = { branch: execSync("git branch --show-current", { encoding: "utf8" }).trim(), commit: execSync("git rev-parse --short HEAD", { encoding: "utf8" }).trim(), remote: execSync("git remote get-url origin", { encoding: "utf8" }).trim() }; } catch (e) { } } return app; } function generateAppId() { if (config.appId) return config.appId; if (process.env.REPL_ID) return `replit-${process.env.REPL_ID}`; if (process.env.GITHUB_REPOSITORY) return `github-${process.env.GITHUB_REPOSITORY.replace("/", "-")}`; if (process.env.VERCEL_URL) return `vercel-${process.env.VERCEL_URL}`; if (process.env.HEROKU_APP_NAME) return `heroku-${process.env.HEROKU_APP_NAME}`; try { const pkg = JSON.parse(fs.readFileSync("./package.json", "utf8")); return `npm-${pkg.name}-${nanoid(8)}`; } catch (e) { return `chitty-${nanoid()}`; } } function detectAppName() { if (config.appName) return config.appName; return process.env.CHITTY_APP_NAME || process.env.REPL_SLUG || process.env.GITHUB_REPOSITORY || process.env.VERCEL_URL || process.env.HEROKU_APP_NAME || process.env.npm_package_name || (() => { try { const pkg = JSON.parse(fs.readFileSync("./package.json", "utf8")); return pkg.name; } catch (e) { return "chittyos-app"; } })(); } function detectVersion() { try { const pkg = JSON.parse(fs.readFileSync("./package.json", "utf8")); return pkg.version; } catch (e) { return "0.0.0"; } } function detectPlatform() { if (process.env.REPL_ID) return "replit"; if (process.env.GITHUB_ACTIONS) return "github-actions"; if (process.env.VERCEL) return "vercel"; if (process.env.NETLIFY) return "netlify"; if (process.env.RENDER) return "render"; if (process.env.HEROKU_APP_NAME) return "heroku"; if (process.env.AWS_LAMBDA_FUNCTION_NAME) return "aws-lambda"; if (process.env.GOOGLE_CLOUD_PROJECT) return "google-cloud"; if (process.env.WEBSITE_INSTANCE_ID) return "azure"; if (process.env.CF_PAGES) return "cloudflare-pages"; if (process.env.CLOUDFLARE_ACCOUNT_ID) return "cloudflare-workers"; return "unknown"; } function detectClaudeCode() { return process.env.CLAUDE_CODE === "true" || fs.existsSync(".claude") || fs.existsSync("CLAUDE.md") || fs.existsSync("claude.json"); } function detectChittyModules() { const modules = []; try { const pkg = JSON.parse(fs.readFileSync("./package.json", "utf8")); const deps = { ...pkg.dependencies, ...pkg.devDependencies }; for (const dep of Object.keys(deps)) { if (dep.startsWith("@chittyos/") || dep.startsWith("@chittycorp/")) { modules.push(dep); } } } catch (e) { } return modules; } async function sendBeacon(event, data) { if (!config.enabled) return; const payload = { ...appInfo, event, timestamp: (/* @__PURE__ */ new Date()).toISOString(), uptime: process.uptime(), ...data }; try { const response = await fetch(`${config.endpoint}/track`, { method: "POST", headers: { "Content-Type": "application/json", "User-Agent": "@chittyos/core/1.0.0" }, body: JSON.stringify(payload) }); if (!config.silent && !response.ok) { console.log(`[ChittyBeacon] Response: ${response.status}`); } } catch (error) { if (!config.silent) { console.log(`[ChittyBeacon] Error: ${error.message}`); } } } function init(customConfig) { if (customConfig) { configure(customConfig); } if (!config.enabled) { if (!config.silent) { console.log("[ChittyBeacon] Disabled"); } return; } appInfo = detectApp(); sendBeacon("startup"); heartbeatInterval = setInterval(() => { sendBeacon("heartbeat"); }, config.interval); heartbeatInterval.unref(); const shutdown = () => { sendBeacon("shutdown"); }; process.once("exit", shutdown); process.once("SIGINT", shutdown); process.once("SIGTERM", shutdown); if (!config.silent) { console.log(`[ChittyBeacon] Tracking ${appInfo.name} on ${appInfo.platform}`); } } function stop() { if (heartbeatInterval) { clearInterval(heartbeatInterval); heartbeatInterval = null; } sendBeacon("stopped"); } if (process.env.NODE_ENV !== "test") { init(); } // src/id/index.ts var id_exports = {}; __export(id_exports, { configure: () => configure2, default: () => id_default, generate: () => generate, getSessionContext: () => getSessionContext, isValidChittyID: () => isValidChittyID, parseChittyID: () => parseChittyID, requestChittyID: () => requestChittyID, setSessionContext: () => setSessionContext, signData: () => signData, validateRemote: () => validateRemote, verifySignature: () => verifySignature }); import * as crypto from "crypto"; var DEFAULT_CONFIG2 = { endpoint: process.env.CHITTY_ID_ENDPOINT || "https://id.chitty.cc", apiKey: process.env.CHITTY_ID_API_KEY, generateKeys: true }; var config2 = { ...DEFAULT_CONFIG2 }; function configure2(customConfig) { config2 = { ...config2, ...customConfig }; } async function requestChittyID(metadata) { if (!config2.apiKey) { throw new Error("ChittyID request requires API key authentication to access id.chitty.cc service"); } try { const response = await fetch(`${config2.endpoint}/api/pipeline/generate`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config2.apiKey}` }, body: JSON.stringify({ metadata, // Include session context for distributed sync sessionId: globalThis.chittySessionId || void 0 }) }); if (!response.ok) { if (response.status === 401) { throw new Error("ChittyID request failed: Invalid or expired API key for id.chitty.cc"); } if (response.status === 403) { throw new Error("ChittyID request failed: Insufficient permissions for id.chitty.cc service"); } throw new Error(`ChittyID service error: ${response.status} - ${response.statusText}`); } const result = await response.json(); if (result.metadata?.sessionId) { globalThis.chittySessionId = result.metadata.sessionId; } return result; } catch (error) { throw error; } } async function generate(metadata) { if (!config2.endpoint) { throw new Error("ChittyID service endpoint not configured - set CHITTY_ID_ENDPOINT to id.chitty.cc"); } return await requestChittyID(metadata); } function verifySignature(chittyId, signature, data, publicKey) { try { const verify = crypto.createVerify("SHA256"); verify.update(data); return verify.verify(publicKey, signature, "base64"); } catch (error) { return false; } } function signData(data, privateKey) { const sign = crypto.createSign("SHA256"); sign.update(data); return sign.sign(privateKey, "base64"); } function isValidChittyID(id) { return /^CID_[A-Za-z0-9_-]{21}$/.test(id); } function parseChittyID(input) { if (isValidChittyID(input)) return input; const cidMatch = input.match(/CID_[A-Za-z0-9_-]{21}/); if (cidMatch) return cidMatch[0]; return null; } async function validateRemote(chittyId) { try { const response = await fetch(`${config2.endpoint}/api/validate/${chittyId}`, { method: "GET", headers: { ...config2.apiKey && { "Authorization": `Bearer ${config2.apiKey}` } } }); if (response.ok) { const result = await response.json(); return result.valid === true; } return false; } catch (error) { console.warn("[ChittyID] Validation service unavailable, using local validation"); return isValidChittyID(chittyId); } } function getSessionContext() { return globalThis.chittySessionId; } function setSessionContext(sessionId) { globalThis.chittySessionId = sessionId; } var id_default = { configure: configure2, generate, requestChittyID, validateRemote, verifySignature, signData, isValidChittyID, parseChittyID, getSessionContext, setSessionContext }; // src/auth/index.ts var auth_exports = {}; __export(auth_exports, { cleanupSessions: () => cleanupSessions, configure: () => configure3, createToken: () => createToken, default: () => auth_default, hasPermissions: () => hasPermissions, hasRoles: () => hasRoles, hashPassword: () => hashPassword, refreshToken: () => refreshToken, revokeSession: () => revokeSession, verifyPassword: () => verifyPassword, verifyToken: () => verifyToken }); import { SignJWT, jwtVerify } from "jose"; import { nanoid as nanoid2 } from "nanoid"; import * as crypto2 from "crypto"; var DEFAULT_CONFIG3 = { jwtSecret: process.env.CHITTY_JWT_SECRET || crypto2.randomBytes(32).toString("base64"), issuer: "chittyos", audience: "chittyos-apps", expiresIn: "24h" }; var config3 = { ...DEFAULT_CONFIG3 }; var sessions = /* @__PURE__ */ new Map(); function configure3(customConfig) { config3 = { ...config3, ...customConfig }; } async function createToken(user) { const secret = new TextEncoder().encode(config3.jwtSecret); const expiresAt = /* @__PURE__ */ new Date(); const hours = parseInt(config3.expiresIn?.replace("h", "") || "24"); expiresAt.setHours(expiresAt.getHours() + hours); const token = await new SignJWT({ sub: user.id, chittyId: user.chittyId, email: user.email, roles: user.roles || [], permissions: user.permissions || [], metadata: user.metadata || {} }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setIssuer(config3.issuer).setAudience(config3.audience).setExpirationTime(config3.expiresIn).setJti(nanoid2()).sign(secret); const refreshToken2 = nanoid2(32); const session = { id: nanoid2(), userId: user.id, token, refreshToken: refreshToken2, expiresAt, createdAt: /* @__PURE__ */ new Date() }; sessions.set(session.id, session); sessions.set(refreshToken2, session); return { token, expiresAt, refreshToken: refreshToken2 }; } async function verifyToken(token) { try { const secret = new TextEncoder().encode(config3.jwtSecret); const { payload } = await jwtVerify(token, secret, { issuer: config3.issuer, audience: config3.audience }); return { ...payload, id: payload.sub, chittyId: payload.chittyId, email: payload.email, roles: payload.roles, permissions: payload.permissions, metadata: payload.metadata }; } catch (error) { throw new Error("Invalid or expired token"); } } async function refreshToken(refreshToken2) { const session = sessions.get(refreshToken2); if (!session) { throw new Error("Invalid refresh token"); } if (session.expiresAt < /* @__PURE__ */ new Date()) { sessions.delete(session.id); sessions.delete(session.refreshToken); throw new Error("Session expired"); } const user = await verifyToken(session.token).catch(() => null); if (!user) { throw new Error("Cannot refresh token"); } return createToken({ id: user.id, chittyId: user.chittyId, email: user.email, roles: user.roles, permissions: user.permissions, metadata: user.metadata }); } function revokeSession(sessionId) { const session = sessions.get(sessionId); if (session) { sessions.delete(session.id); sessions.delete(session.refreshToken); return true; } return false; } function hasRoles(user, requiredRoles) { if (!user.roles) return false; return requiredRoles.every((role) => user.roles.includes(role)); } function hasPermissions(user, requiredPermissions) { if (!user.permissions) return false; return requiredPermissions.every((perm) => user.permissions.includes(perm)); } async function hashPassword(password) { const salt = crypto2.randomBytes(16).toString("hex"); const hash = crypto2.pbkdf2Sync(password, salt, 1e5, 64, "sha512").toString("hex"); return `${salt}:${hash}`; } async function verifyPassword(password, hashedPassword) { const [salt, hash] = hashedPassword.split(":"); const verifyHash = crypto2.pbkdf2Sync(password, salt, 1e5, 64, "sha512").toString("hex"); return hash === verifyHash; } function cleanupSessions() { const now = /* @__PURE__ */ new Date(); for (const [key, session] of sessions) { if (session.expiresAt < now) { sessions.delete(key); } } } setInterval(cleanupSessions, 36e5).unref(); var auth_default = { configure: configure3, createToken, verifyToken, refreshToken, revokeSession, hasRoles, hasPermissions, hashPassword, verifyPassword, cleanupSessions }; // src/verify/index.ts var verify_exports = {}; __export(verify_exports, { configure: () => configure4, default: () => verify_default, hashData: () => hashData, sanitizeInput: () => sanitizeInput, schemas: () => schemas, signData: () => signData2, validateChecksum: () => validateChecksum, validateJSON: () => validateJSON, validateSchema: () => validateSchema, verifyIntegrity: () => verifyIntegrity, verifySignedData: () => verifySignedData }); import { z } from "zod"; import * as crypto3 from "crypto"; var DEFAULT_CONFIG4 = { strictMode: false, hashAlgorithm: "sha256" }; var config4 = { ...DEFAULT_CONFIG4 }; function configure4(customConfig) { config4 = { ...config4, ...customConfig }; } function validateSchema(data, schema) { try { const validated = schema.parse(data); return { valid: true, data: validated }; } catch (error) { if (error instanceof z.ZodError) { return { valid: false, errors: error.errors.map((e) => `${e.path.join(".")}: ${e.message}`) }; } return { valid: false, errors: ["Validation failed"] }; } } var schemas = { email: z.string().email(), chittyId: z.string().regex(/^CID_[A-Za-z0-9_-]{21}$/), uuid: z.string().uuid(), url: z.string().url(), phoneNumber: z.string().regex(/^\+?[1-9]\d{1,14}$/), dateTime: z.string().datetime(), ipAddress: z.string().ip(), semver: z.string().regex(/^\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?$/), strongPassword: z.string().min(8).regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/), jwt: z.string().regex(/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/), base64: z.string().regex(/^[A-Za-z0-9+/]*={0,2}$/), hexColor: z.string().regex(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/), creditCard: z.string().regex(/^\d{13,19}$/).refine(luhnCheck, { message: "Invalid credit card number" }) }; function luhnCheck(cardNumber) { const digits = cardNumber.replace(/\D/g, ""); let sum = 0; let isEven = false; for (let i = digits.length - 1; i >= 0; i--) { let digit = parseInt(digits[i], 10); if (isEven) { digit *= 2; if (digit > 9) { digit -= 9; } } sum += digit; isEven = !isEven; } return sum % 10 === 0; } function hashData(data, algorithm = config4.hashAlgorithm) { const stringData = typeof data === "string" ? data : JSON.stringify(data); return crypto3.createHash(algorithm).update(stringData).digest("hex"); } function verifyIntegrity(data, expectedHash, algorithm = config4.hashAlgorithm) { const actualHash = hashData(data, algorithm); return actualHash === expectedHash; } function signData2(data, privateKey, chittyId) { const timestamp = (/* @__PURE__ */ new Date()).toISOString(); const dataToSign = JSON.stringify({ data, timestamp }); const sign = crypto3.createSign("SHA256"); sign.update(dataToSign); const signature = sign.sign(privateKey, "base64"); return { data, signature, timestamp, chittyId }; } function verifySignedData(signedData, publicKey) { try { const dataToVerify = JSON.stringify({ data: signedData.data, timestamp: signedData.timestamp }); const verify = crypto3.createVerify("SHA256"); verify.update(dataToVerify); const isValid = verify.verify(publicKey, signedData.signature, "base64"); return { valid: isValid, errors: isValid ? void 0 : ["Invalid signature"] }; } catch (error) { return { valid: false, errors: ["Signature verification failed"] }; } } async function validateChecksum(filePath, expectedChecksum, algorithm = "sha256") { const fs2 = await import("fs"); const stream = fs2.createReadStream(filePath); const hash = crypto3.createHash(algorithm); return new Promise((resolve, reject) => { stream.on("data", (data) => hash.update(data)); stream.on("end", () => { const actualChecksum = hash.digest("hex"); resolve(actualChecksum === expectedChecksum); }); stream.on("error", reject); }); } function sanitizeInput(input) { let sanitized = input.replace(/[\x00-\x1F\x7F]/g, ""); sanitized = sanitized.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;").replace(/\//g, "&#x2F;"); return sanitized.trim(); } function validateJSON(jsonString) { try { const parsed = JSON.parse(jsonString); return { valid: true, data: parsed }; } catch (error) { return { valid: false, errors: ["Invalid JSON: " + error.message] }; } } var verify_default = { configure: configure4, validateSchema, schemas, hashData, verifyIntegrity, signData: signData2, verifySignedData, validateChecksum, sanitizeInput, validateJSON }; // src/brand/index.ts var brand_exports = {}; __export(brand_exports, { ASCII_LOGO: () => ASCII_LOGO, BRAND_CONFIG: () => BRAND_CONFIG, CHITTY_COLORS: () => CHITTY_COLORS, CHITTY_THEME: () => CHITTY_THEME, default: () => brand_default, generateStyleTag: () => generateStyleTag, generateTailwindConfig: () => generateTailwindConfig, generateThemeProvider: () => generateThemeProvider, getCSSVariables: () => getCSSVariables }); var CHITTY_COLORS = { light: { primary: "#0F172A", secondary: "#64748B", accent: "#3B82F6", background: "#FFFFFF", foreground: "#0F172A", muted: "#F1F5F9", mutedForeground: "#64748B", border: "#E2E8F0", destructive: "#EF4444", success: "#10B981", warning: "#F59E0B", info: "#3B82F6" }, dark: { primary: "#F8FAFC", secondary: "#94A3B8", accent: "#60A5FA", background: "#0F172A", foreground: "#F8FAFC", muted: "#1E293B", mutedForeground: "#94A3B8", border: "#334155", destructive: "#F87171", success: "#34D399", warning: "#FBBF24", info: "#60A5FA" } }; var CHITTY_THEME = { name: "ChittyOS Default", colors: CHITTY_COLORS, fonts: { sans: 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif', serif: 'Georgia, Cambria, "Times New Roman", Times, serif', mono: 'ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", monospace' }, radius: "0.5rem", spacing: { xs: "0.25rem", sm: "0.5rem", md: "1rem", lg: "1.5rem", xl: "2rem" } }; var BRAND_CONFIG = { name: "ChittyOS", tagline: "Intelligent Business Operating System", description: "Enterprise-grade distributed system for legal technology and business automation", logo: { text: "ChittyOS", icon: "\u26A1", svg: null }, copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ChittyOS. All rights reserved.`, social: { github: "https://github.com/chittyos", twitter: null, linkedin: null, discord: null }, support: { email: "support@chitty.cc", docs: "https://docs.chitty.cc", status: "https://status.chitty.cc" } }; function getCSSVariables(theme = "light") { const colors = CHITTY_COLORS[theme]; const vars = []; for (const [key, value] of Object.entries(colors)) { const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase(); vars.push(`--chitty-${cssKey}: ${value};`); } vars.push(`--chitty-font-sans: ${CHITTY_THEME.fonts.sans};`); vars.push(`--chitty-font-serif: ${CHITTY_THEME.fonts.serif};`); vars.push(`--chitty-font-mono: ${CHITTY_THEME.fonts.mono};`); for (const [key, value] of Object.entries(CHITTY_THEME.spacing)) { vars.push(`--chitty-spacing-${key}: ${value};`); } vars.push(`--chitty-radius: ${CHITTY_THEME.radius};`); return vars.join("\n "); } function generateStyleTag(theme = "light") { return ` <style id="chittyos-theme"> :root { ${getCSSVariables(theme)} } .chitty-theme { color: var(--chitty-foreground); background-color: var(--chitty-background); font-family: var(--chitty-font-sans); } .chitty-primary { color: var(--chitty-primary); } .chitty-secondary { color: var(--chitty-secondary); } .chitty-accent { color: var(--chitty-accent); } .chitty-muted { color: var(--chitty-muted-foreground); background-color: var(--chitty-muted); } .chitty-border { border-color: var(--chitty-border); } .chitty-btn { padding: var(--chitty-spacing-sm) var(--chitty-spacing-md); border-radius: var(--chitty-radius); background-color: var(--chitty-primary); color: var(--chitty-background); border: none; cursor: pointer; font-family: var(--chitty-font-sans); } .chitty-btn:hover { opacity: 0.9; } .chitty-card { padding: var(--chitty-spacing-md); border-radius: var(--chitty-radius); background-color: var(--chitty-background); border: 1px solid var(--chitty-border); box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1); } .chitty-input { padding: var(--chitty-spacing-sm); border-radius: var(--chitty-radius); background-color: var(--chitty-background); color: var(--chitty-foreground); border: 1px solid var(--chitty-border); font-family: var(--chitty-font-sans); } .chitty-input:focus { outline: none; border-color: var(--chitty-accent); box-shadow: 0 0 0 2px rgb(59 130 246 / 0.1); } .chitty-badge { padding: var(--chitty-spacing-xs) var(--chitty-spacing-sm); border-radius: calc(var(--chitty-radius) * 0.5); background-color: var(--chitty-muted); color: var(--chitty-muted-foreground); font-size: 0.875rem; font-weight: 500; } .chitty-code { padding: var(--chitty-spacing-xs); border-radius: calc(var(--chitty-radius) * 0.5); background-color: var(--chitty-muted); color: var(--chitty-foreground); font-family: var(--chitty-font-mono); font-size: 0.875rem; } </style>`; } function generateThemeProvider() { return ` import React, { createContext, useContext, useState } from 'react' const ThemeContext = createContext({ theme: 'light', toggleTheme: () => {}, colors: ${JSON.stringify(CHITTY_COLORS.light, null, 2)} }) export function ChittyThemeProvider({ children }) { const [theme, setTheme] = useState('light') const toggleTheme = () => { setTheme(prev => prev === 'light' ? 'dark' : 'light') } const colors = theme === 'light' ? ${JSON.stringify(CHITTY_COLORS.light, null, 2)} : ${JSON.stringify(CHITTY_COLORS.dark, null, 2)} return ( <ThemeContext.Provider value={{ theme, toggleTheme, colors }}> {children} </ThemeContext.Provider> ) } export const useChittyTheme = () => useContext(ThemeContext) `; } function generateTailwindConfig() { return { theme: { extend: { colors: { chitty: { primary: "var(--chitty-primary)", secondary: "var(--chitty-secondary)", accent: "var(--chitty-accent)", background: "var(--chitty-background)", foreground: "var(--chitty-foreground)", muted: "var(--chitty-muted)", "muted-foreground": "var(--chitty-muted-foreground)", border: "var(--chitty-border)", destructive: "var(--chitty-destructive)", success: "var(--chitty-success)", warning: "var(--chitty-warning)", info: "var(--chitty-info)" } }, fontFamily: { "chitty-sans": CHITTY_THEME.fonts.sans.split(","), "chitty-serif": CHITTY_THEME.fonts.serif.split(","), "chitty-mono": CHITTY_THEME.fonts.mono.split(",") }, borderRadius: { "chitty": CHITTY_THEME.radius }, spacing: { "chitty-xs": CHITTY_THEME.spacing.xs, "chitty-sm": CHITTY_THEME.spacing.sm, "chitty-md": CHITTY_THEME.spacing.md, "chitty-lg": CHITTY_THEME.spacing.lg, "chitty-xl": CHITTY_THEME.spacing.xl } } } }; } var ASCII_LOGO = ` _____ _ _ _ _ ____ _____ / ____| | (_) | | | / __ \\ / ____| | | | |__ _| |_| |_ _ _| | | | (___ | | | '_ \\| | __| __| | | | | | |\\___ \\ | |____| | | | | |_| |_| |_| | |__| |____) | \\_____|_| |_|_|\\__|\\__|\\__, |\\____/|_____/ __/ | |___/ `; var brand_default = { CHITTY_COLORS, CHITTY_THEME, BRAND_CONFIG, getCSSVariables, generateStyleTag, generateThemeProvider, generateTailwindConfig, ASCII_LOGO }; // src/canon/index.ts var canon_exports = {}; __export(canon_exports, { clearCanonCache: () => clearCanonCache, configure: () => configure5, createCanonical: () => createCanonical, default: () => canon_default, getCanonStats: () => getCanonStats, getCanonical: () => getCanonical, getCanonicalHistory: () => getCanonicalHistory, mergeCanonical: () => mergeCanonical, queryCanonical: () => queryCanonical, signCanonical: () => signCanonical, updateCanonical: () => updateCanonical, validateCanonical: () => validateCanonical, verifyCanonicalSignature: () => verifyCanonicalSignature }); import { nanoid as nanoid3 } from "nanoid"; import * as crypto4 from "crypto"; var DEFAULT_CONFIG5 = { endpoint: process.env.CHITTY_CANON_ENDPOINT || "https://canon.chitty.cc", enableChain: true, enableSignatures: true }; var config5 = { ...DEFAULT_CONFIG5 }; var canonCache = /* @__PURE__ */ new Map(); var chainIndex = /* @__PURE__ */ new Map(); function configure5(customConfig) { config5 = { ...config5, ...customConfig }; } function createCanonical(data, chittyId, metadata) { const canonId = `CANON_${nanoid3(21)}`; const timestamp = (/* @__PURE__ */ new Date()).toISOString(); const hash = crypto4.createHash("sha256").update(JSON.stringify({ data, chittyId, timestamp })).digest("hex"); const record = { id: nanoid3(), canonId, version: 1, data, hash, chittyId, timestamp, metadata: { source: metadata?.source || "chittyos-core", tags: metadata?.tags || [], ttl: metadata?.ttl, immutable: metadata?.immutable || false } }; canonCache.set(canonId, record); if (config5.enableChain) { chainIndex.set(canonId, [record]); } return record; } function updateCanonical(canonId, data, chittyId) { const existing = canonCache.get(canonId); if (!existing) { return null; } if (existing.metadata?.immutable) { throw new Error("Cannot update immutable canonical record"); } const timestamp = (/* @__PURE__ */ new Date()).toISOString(); const previousHash = existing.hash; const hash = crypto4.createHash("sha256").update(JSON.stringify({ data, chittyId, timestamp, previousHash })).digest("hex"); const record = { ...existing, id: nanoid3(), version: existing.version + 1, data, hash, previousHash, chittyId, timestamp }; canonCache.set(canonId, record); if (config5.enableChain) { const chain = chainIndex.get(canonId) || []; chain.push(record); chainIndex.set(canonId, chain); } return record; } async function getCanonical(canonId) { if (canonCache.has(canonId)) { return canonCache.get(canonId); } if (config5.storageAdapter) { const record = await config5.storageAdapter.get(canonId); if (record) { canonCache.set(canonId, record); return record; } } if (config5.endpoint) { try { const response = await fetch(`${config5.endpoint}/canon/${canonId}`); if (response.ok) { const record = await response.json(); canonCache.set(canonId, record); return record; } } catch (error) { console.error("[Canon] Failed to fetch from endpoint:", error); } } return null; } function getCanonicalHistory(canonId) { return chainIndex.get(canonId) || []; } function validateCanonical(record) { const errors = []; const warnings = []; if (!record.canonId || !record.canonId.startsWith("CANON_")) { errors.push("Invalid canon ID format"); } if (!record.hash) { errors.push("Missing hash"); } if (!record.chittyId) { errors.push("Missing ChittyID"); } const expectedHash = crypto4.createHash("sha256").update(JSON.stringify({ data: record.data, chittyId: record.chittyId, timestamp: record.timestamp, ...record.previousHash && { previousHash: record.previousHash } })).digest("hex"); if (record.hash !== expectedHash) { errors.push("Hash mismatch - data integrity compromised"); } if (record.previousHash && record.version > 1) { const history = getCanonicalHistory(record.canonId); const previousRecord = history[record.version - 2]; if (previousRecord && previousRecord.hash !== record.previousHash) { errors.push("Chain integrity violation - previous hash mismatch"); } } if (record.metadata?.ttl) { const age = Date.now() - new Date(record.timestamp).getTime(); const ttlMs = record.metadata.ttl * 1e3; if (age > ttlMs) { warnings.push("Record has exceeded TTL"); } } return { valid: errors.length === 0, errors: errors.length > 0 ? errors : void 0, warnings: warnings.length > 0 ? warnings : void 0 }; } function signCanonical(record, privateKey) { if (!config5.enableSignatures) { return record; } const sign = crypto4.createSign("SHA256"); sign.update(record.hash); const signature = sign.sign(privateKey, "base64"); return { ...record, signature }; } function verifyCanonicalSignature(record, publicKey) { if (!record.signature) { return false; } try { const verify = crypto4.createVerify("SHA256"); verify.update(record.hash); return verify.verify(publicKey, record.signature, "base64"); } catch (error) { return false; } } function mergeCanonical(records, strategy = "latest", customMerge) { if (records.length === 0) { throw new Error("No records to merge"); } if (records.length === 1) { return records[0]; } let winner; switch (strategy) { case "latest": winner = records.reduce( (latest, record) => new Date(record.timestamp) > new Date(latest.timestamp) ? record : latest ); break; case "highest-version": winner = records.reduce( (highest, record) => record.version > highest.version ? record : highest ); break; case "custom": if (!customMerge) { throw new Error("Custom merge function required"); } const mergedData = customMerge(records); winner = createCanonical( mergedData, records[0].chittyId, { source: "merge", tags: ["merged"] } ); break; default: winner = records[0]; } return { ...winner, metadata: { ...winner.metadata, source: "merge", tags: [...winner.metadata?.tags || [], "merged", `from-${records.length}-records`] } }; } async function queryCanonical(filter) { let results = []; for (const record of canonCache.values()) { let matches = true; if (filter.chittyId && record.chittyId !== filter.chittyId) { matches = false; } if (filter.tags && filter.tags.length > 0) { const recordTags = record.metadata?.tags || []; if (!filter.tags.every((tag) => recordTags.includes(tag))) { matches = false; } } if (filter.source && record.metadata?.source !== filter.source) { matches = false; } if (filter.afterTimestamp && record.timestamp <= filter.afterTimestamp) { matches = false; } if (filter.beforeTimestamp && record.timestamp >= filter.beforeTimestamp) { matches = false; } if (matches) { results.push(record); } } if (config5.storageAdapter) { const storedRecords = await config5.storageAdapter.list(filter); results = [...results, ...storedRecords]; } const seen = /* @__PURE__ */ new Set(); results = results.filter((record) => { if (seen.has(record.canonId)) { return false; } seen.add(record.canonId); return true; }); return results; } function clearCanonCache() { canonCache.clear(); chainIndex.clear(); } function getCanonStats() { let oldest; let newest; for (const record of canonCache.values()) { if (!oldest || record.timestamp < oldest) { oldest = record.timestamp; } if (!newest || record.timestamp > newest) { newest = record.timestamp; } } return { totalRecords: canonCache.size, totalChains: chainIndex.size, cacheSize: JSON.stringify([...canonCache.values()]).length, oldestRecord: oldest, newestRecord: newest }; } var canon_default = { configure: configure5, createCanonical, updateCanonical, getCanonical, getCanonicalHistory, validateCanonical, signCanonical, verifyCanonicalSignature, mergeCanonical, queryCanonical, clearCanonCache, getCanonStats }; // src/registry/index.ts var registry_exports = {}; __export(registry_exports, { connectToService: () => connectToService, default: () => registry_default, getAllServices: () => getAllServices, getRegistry: () => getRegistry, getService: () => getService, registerService: () => registerService }); import { EventEmitter } from "eventemitter3"; import { nanoid as nanoid4 } from "nanoid"; var ServiceRegistry = class extends EventEmitter { config; services = /* @__PURE__ */ new Map(); connections = /* @__PURE__ */ new Map(); healthStatus = /* @__PURE__ */ new Map(); healthCheckTimers = /* @__PURE__ */ new Map(); discoveryTimer = null; constructor(config6 = {}) { super(); this.config = { discoveryEndpoint: config6.discoveryEndpoint || process.env.CHITTY_REGISTRY_ENDPOINT || "https://registry.chitty.cc", healthCheckInterval: config6.healthCheckInterval || 3e4, connectionTimeout: config6.connectionTimeout || 1e4, maxRetries: config6.maxRetries || 3, enableAutoDiscovery: config6.enableAutoDiscovery ?? true }; if (this.config.enableAutoDiscovery) { this.startAutoDiscovery(); } } /** * Register a service endpoint */ registerService(service) { const registeredService = { ...service, id: service.name + "_" + nanoid4(8) }; try { const url = new URL(service.url); registeredService.protocol = url.protocol.replace(":", ""); registeredService.host = url.hostname; registeredService.port = url.port ? parseInt(url.port) : void 0; registeredService.path = url.pathname !== "/" ? url.pathname : void 0; } catch (error) { console.warn("[Registry] Invalid URL for service:", service.name); } this.services.set(registeredService.id, registeredService); this.emit("service:registered", registeredService); this.startHealthCheck(registeredService.id); sendBeacon("registry_service_registered", { serviceId: registeredService.id, name: registeredService.name, type: registeredService.type }); return registeredService; } /** * Unregister a service */ unregisterService(serviceId) { const service = this.services.get(serviceId); if (!service) { return false; } this.stopHealthCheck(serviceId); for (const [connId, conn] of this.connections) { if (conn.serviceId === serviceId) { this.disconnectConnection(connId); } } this.services.delete(serviceId); this.healthStatus.delete(serviceId); this.emit("service:unregistered", serviceId); return true; } /** * Get service by ID or name */ getService(idOrName) { if (this.services.has(idOrName)) { return this.services.get(idOrName); } for (const service of this.services.values()) { if (service.name === idOrName) { return service; } } return void 0; } /** * Get all services of a specific type */ getServicesByType(type2) { return Array.from(this.services.values()).filter((s) => s.type === type2); } /** * Establish connection to a service */ async connectToService(serviceId, chittyId, metadata) { const service = this.services.get(serviceId); if (!service) { throw new Error(`Service ${serviceId} not found`); } const connection = { id: `conn_${nanoid4()}`, serviceId, chittyId, status: "connecting", metadata }; this.connections.set(connection.id, connection); try { const startTime = Date.now(); await this.testConnection(service); const latency = Date.now() - startTime; connection.status = "connected"; connection.establishedAt = (/* @__PURE__ */ new Date()).toISOString(); connection.latency = latency; this.connections.set(connection.id, connection); this.emit("connection:established", connection); sendBeacon("registry_connection_established", { serviceId, chittyId, latency }); return connection; } catch (error) { connection.status = "error"; connection.error = error.message; this.connections.set(connection.id, connection); throw error; } } /** * Disconnect a connection */ disconnectConnection(connectionId) { const connection = this.connections.get(connectionId); if (!connection) { return false; } connection.status = "disconnected"; this.emit("connection:lost", connection); this.connections.delete(connectionId); return true; } /** * Get connection status */ getConnection(connectionId) { return this.connections.get(connectionId); } /** * Get all connections for a ChittyID */ getConnectionsByChittyId(chittyId) { return Array.from(this.connections.values()).filter((c) => c.chittyId === chittyId); } /** * Test connection to a service */ async testConnection(service) { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), this.config.connectionTimeout); try { const response = await fetch(service.url, { method: "HEAD", signal: controller.signal }); if (!response.ok && response.status !== 405) { throw new Error(`Service returned ${response.status}`); } } catch (error) { if (error.name === "AbortError") { throw new Error("Connection timeout"); } throw error; } finally { clearTimeout(timeout); } } /** * Perform health check on a service */ async performHealthCheck(serviceId) { const service = this.services.get(serviceId); if (!service) { return; } const health = { serviceId, status: "unknown", lastCheckAt: (/* @__PURE__ */ new Date()).toISOString(), checks: [] }; try { const startTime = Date.now(); await this.testConnection(service); const responseTime = Date.now() - startTime; health.responseTime = responseTime; health.status = responseTime < 1e3 ? "healthy" : "degraded"; health.checks.push({ name: "connectivity", status: "pass", message: `Response time: ${responseTime}ms` }); try { const healthUrl = new URL(service.url); healthUrl.pathname = "/health"; const healthResponse = await fetch(healthUrl.toString(), { signal: AbortSignal.timeout(5e3) }); if (healthResponse.ok) { const healthData = await healthResponse.json(); if (healthData.status) { health.status = healthData.status; } if (healthData.checks) { health.checks.push(...healthData.checks); } } } catch (error) { } this.healthStatus.set(serviceId, health); if (health.status === "healthy") { this.emit("service:healthy", serviceId); } else if (health.status === "unhealthy") { this.emit("service:unhealthy", serviceId, "Health check failed"); } } catch (error) { health.status = "unhealthy"; health.checks.push({ name: "connectivity", status: "fail", message: error.message }); this.healthStatus.set(serviceId, health); this.emit("service:unhealthy", serviceId, error.message); } } /** * Start health checks for a service */ startHealthCheck(serviceId) { this.performHealthCheck(serviceId); const timer = setInterval(() => { this.performHealthCheck(serviceId); }, this.config.healthCheckInterval); this.healthCheckTimers.set(serviceId, timer); } /** * Stop health checks for a service */ stopHealthCheck(serviceId) { const timer = this.healthCheckTimers.get(serviceId); if (timer) { clearInterval(timer); this.healthCheckTimers.delete(serviceId); } } /** * Auto-discover services from registry endpoint */ async discoverServices() { if (!this.config.discoveryEndpoint) { return; } try { const response = await fetch(`${this.config.discoveryEndpoint}/discover`); if (response.ok) { const services = await response.json(); for (const service of services) { if (!this.getService(service.id)) { this.registerService(service); } } this.emit("discovery:update", services); } } catch (error) { console.error("[Registry] Discovery failed:", error); } } /** * Start auto-discovery */ startAutoDiscovery() { this.discoverServices(); this.discoveryTimer = setInterval(() => { this.discoverServices(); }, 6e4); } /** * Stop auto-discovery */ stopAutoDiscovery() { if (this.discoveryTimer) { clearInterval(this.discoveryTimer); this.discoveryTimer = null; } } /** * Get service health status */ getHealth(serviceId) { return this.healthStatus.get(serviceId); } /** * Get all registered services */ getAllServices() { return Array.from(this.services.values()); } /** * Get all active connections */ getAllConnections() { return Array.from(this.connections.values()); } /** * Get registry statistics */ getStats() { const healthyServices = Array.from(this.healthStatus.values()).filter((h) => h.status === "healthy").length; const unhealthyServices = Array.from(this.healthStatus.values()).filter((h) => h.status === "unhealthy").length; const activeConnections = Array.from(this.connections.values()).filter((c) => c.status === "connected").length; return { totalServices: this.services.size, healthyServices, unhealthyServices, totalConnections: this.connections.size, activeConnections }; } /** * Cleanup and shutdown */ shutdown() { for (const serviceId of this.healthCheckTimers.keys()) { this.stopHealthCheck(serviceId); } this.stopAutoDiscovery(); this.services.clear(); this.connections.clear(); this.healthStatus.clear(); } }; var registryInstance = null; function getRegistry(config6) { if (!registryInstance) { registryInstance = new ServiceRegistry(config6); } return registryInstance; } function registerService(service) { return getRegistry().registerService(service); } function connectToService(serviceId, chittyId, metadata) { return getRegistry().connectToService(serviceId, chittyId, metadata); } function getService(idOrName) { return getRegistry().getService(idOrName); } function getAllServices() { return getRegistry().getAllServices(); } var registry_default = { getRegistry, registerService, connectToService, getService, getAllServices, ServiceRegistry }; // src/chittychat/index.ts var chittychat_exports = {}; __export(chittychat_exports, { default: () => chittychat_default, getChittyChat: () => getChittyChat }); import { EventEmitter as EventEmitter2 } from "eventemitter3"; var ChittyChatClient = class extends EventEmitter2 { config; ws = null; constructor(config6 = {}) { super(); this.config = { endpoint: config6.endpoint || process.env.CHITTY_CHAT_ENDPOINT || "https://chat.chitty.cc", wsEndpoint: config6.wsEndpoint || process.env.CHITTY_CHAT_WS || "wss://ws.chitty.cc", apiKey: config6.apiKey || process.env.CHITTY_CHAT_API_KEY }; } async connect(chittyId) { const url = `${this.config.wsEndpoint}?chittyId=${chittyId}`; this.ws = new WebSocket(url); return new Promise((resolve, reject) => { this.ws.onopen = () => { sendBeacon("chittychat_connected", { chittyId }); resolve(); }; this.ws.onerror = (error) => reject(error); this.ws.onmessage = (event) => { this.emit("message", JSON.parse(event.data)); }; }); } async send(message) { if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { throw new Error("Not connected to ChittyChat"); } this.ws.send(JSON.stringify(message)); sendBeacon("chittychat_message_sent"); } disconnect() { if (this.ws) { this.ws.close(); this.ws = null; } } }; var clientInstance = null; function getChittyChat(config6) { if (!clientInstance) { clientInstance = new ChittyChatClient(config6); } return clientInstance; } var chittychat_default = { getChittyChat, ChittyChatClient }; // src/index.ts var index_default = { beacon: beacon_exports, id: id_exports, auth: auth_exports, verify: verify_exports, brand: brand_exports, canon: canon_exports, registry: registry_exports, chittychat: chittychat_exports }; if (typeof process !== "undefined" && process.env.CHITTY_BEACON_DISABLED !== "true") { init(); } var VERSION = "1.0.0"; if (typeof process !== "undefined" && process.env.NODE_ENV === "development") { console.log(ASCII_LOGO); console.log(`ChittyOS Core v${VERSION} initialized`); } export { ASCII_LOGO, BRAND_CONFIG, CHITTY_COLORS, CHITTY_THEME, VERSION, auth_exports as auth, beacon_exports as beacon, brand_exports as brand, canon_exports as canon, chittychat_exports as chittychat, configure as configureBeacon, connectToService, createCanonical, createToken, index_default as default, detectApp, generate as generateChittyID, generateStyleTag, generateTailwindConfig, getAllServices, getCSSVariables, getCanonical, getChittyChat, getRegistry, getService, getSessionContext, hasPermissions, hasRoles, hashData, hashPassword, id_exports as id, init as initBeacon, isValidChittyID, mergeCanonical, parseChittyID, queryCanonical, refreshToken, registerService, registry_exports as registry, requestChittyID, revokeSession, sanitizeInput, sendBeacon, setSessionContext, signData2 as signData, signData as signWithChittyID, updateCanonical, validateCanonical, validateRemote as validateChittyID, validateJSON, validateSchema, schemas as validationSchemas, verify_exports as verify, verifySignature as verifyChittySignature, verifyIntegrity, verifyPassword, verifySignedData, verifyToken }; //# sourceMappingURL=index.mjs.map