// Mirrored from docs/viz/modules-data.js (public product catalogue). Regenerate on catalogue change.
// content module status overridden to "available" — shipped as @platform-modules/content@0.0.1.

export type Capability = {
  name: string;
  kind: string;
  desc: string;
  status?: string;
};

export type Provider = Capability & {
  id?: string;
  region?: string;
  [key: string]: unknown;
};

export type Module = {
  id: string;
  name: string;
  pkg: string;
  layer: string;
  status: string;
  tagline: string;
  deps: string[];
  capabilities: Capability[];
  providers?: Provider[];
  verified?: boolean;
  sibling?: string;
};

export type Blueprint = {
  id: string;
  kind: string;
  name: string;
  status: string;
  tagline: string;
  presets: string[];
  plugins: string[];
  deps: string[];
  modules: string[];
};

export type Layer = {
  id: string;
  name: string;
  blurb: string;
};

export const layers: Layer[] = [
  {
    "id": "L0",
    "name": "Foundation",
    "blurb": "Zero-dependency building blocks. Everything sits on these."
  },
  {
    "id": "L1",
    "name": "Core infrastructure",
    "blurb": "Jobs, mail, auth, tenancy, cache — the spine of an app."
  },
  {
    "id": "L2",
    "name": "Domain primitives",
    "blurb": "Money, search, uploads, AI and more — composable capabilities."
  },
  {
    "id": "L3",
    "name": "Composite",
    "blurb": "Bolt-on features assembled from the primitives below."
  },
  {
    "id": "UI",
    "name": "UI kit",
    "blurb": "Accessible, themeable React components and design tokens. The look layer the modules surface through — not another core tier."
  }
];

export const modules: Module[] = [
  {
    "id": "util",
    "name": "util",
    "pkg": "@platform-modules/util",
    "layer": "L0",
    "status": "available",
    "tagline": "Zero-dependency building blocks every app needs, all edge-safe.",
    "deps": [],
    "capabilities": [
      {
        "name": "crypto",
        "kind": "capability",
        "desc": "Edge-safe cryptography — constant-time compare and HMAC-SHA256.",
        "status": "ready"
      },
      {
        "name": "tokens",
        "kind": "capability",
        "desc": "Generate and verify signed, expiring tokens.",
        "status": "ready"
      },
      {
        "name": "password",
        "kind": "capability",
        "desc": "Password hashing and verification (Web Crypto, Workers-safe).",
        "status": "ready"
      },
      {
        "name": "rate-limit",
        "kind": "capability",
        "desc": "Throttle requests across memory, KV, database, or edge counters.",
        "status": "soon"
      },
      {
        "name": "idempotency",
        "kind": "capability",
        "desc": "Make repeated operations safe to retry exactly once.",
        "status": "soon"
      },
      {
        "name": "ssrf-guard",
        "kind": "capability",
        "desc": "Block server-side request forgery to internal addresses.",
        "status": "soon"
      },
      {
        "name": "config",
        "kind": "capability",
        "desc": "Typed, validated environment configuration.",
        "status": "soon"
      },
      {
        "name": "logger",
        "kind": "capability",
        "desc": "Structured logging.",
        "status": "soon"
      },
      {
        "name": "error-reporter",
        "kind": "capability",
        "desc": "Capture and report errors.",
        "status": "soon"
      },
      {
        "name": "id",
        "kind": "capability",
        "desc": "Sortable unique identifiers.",
        "status": "ready"
      },
      {
        "name": "datetime",
        "kind": "capability",
        "desc": "Date and time helpers.",
        "status": "ready"
      },
      {
        "name": "timezone",
        "kind": "capability",
        "desc": "Timezone-aware conversions.",
        "status": "ready"
      },
      {
        "name": "cron",
        "kind": "capability",
        "desc": "Parse and evaluate cron schedules.",
        "status": "soon"
      },
      {
        "name": "http-cache-headers",
        "kind": "capability",
        "desc": "Build correct HTTP cache-control headers.",
        "status": "soon"
      },
      {
        "name": "full-text-search",
        "kind": "capability",
        "desc": "Safe full-text query building, ranking, and highlighting.",
        "status": "ready"
      },
      {
        "name": "result",
        "kind": "capability",
        "desc": "Typed success / error result values.",
        "status": "soon"
      },
      {
        "name": "validation",
        "kind": "capability",
        "desc": "Schema validation helpers.",
        "status": "soon"
      },
      {
        "name": "sanitize-html",
        "kind": "capability",
        "desc": "Sanitize untrusted HTML.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "db",
    "name": "db",
    "pkg": "@platform-modules/db",
    "layer": "L0",
    "status": "available",
    "tagline": "One typed database contract you write once and run on any Postgres driver.",
    "deps": [],
    "capabilities": [
      {
        "name": "typed-contract",
        "kind": "capability",
        "desc": "A typed Database / Transaction / Querier contract with zero runtime weight.",
        "status": "ready"
      }
    ],
    "providers": [
      {
        "name": "neon-http",
        "kind": "provider",
        "desc": "Neon over HTTP — stateless, edge-friendly.",
        "status": "ready"
      },
      {
        "name": "neon-serverless",
        "kind": "provider",
        "desc": "Neon serverless driver with transactions.",
        "status": "ready"
      },
      {
        "name": "postgres-js",
        "kind": "provider",
        "desc": "Standard PostgreSQL via postgres.js.",
        "status": "ready"
      },
      {
        "name": "pglite",
        "kind": "provider",
        "desc": "In-process Postgres for tests and local dev.",
        "status": "ready"
      }
    ]
  },
  {
    "id": "jobs",
    "name": "jobs",
    "pkg": "@platform-modules/jobs",
    "layer": "L1",
    "status": "available",
    "tagline": "Background jobs and queues with retries and idempotency, runtime-agnostic.",
    "deps": [
      "db"
    ],
    "capabilities": [
      {
        "name": "handler-registry",
        "kind": "capability",
        "desc": "Register typed job handlers with ack / retry.",
        "status": "ready"
      },
      {
        "name": "idempotency",
        "kind": "capability",
        "desc": "Process each job exactly once.",
        "status": "ready"
      }
    ],
    "providers": [
      {
        "name": "cf-queues",
        "kind": "provider",
        "desc": "Cloudflare Queues.",
        "status": "ready"
      },
      {
        "name": "db-poll",
        "kind": "provider",
        "desc": "Database-backed queue (skip-locked, backoff, dead-letter).",
        "status": "ready"
      },
      {
        "name": "do-runner",
        "kind": "provider",
        "desc": "Durable Object alarms for self-rescheduling jobs.",
        "status": "ready"
      },
      {
        "name": "outbox",
        "kind": "provider",
        "desc": "Transactional outbox — emit events atomically with your data.",
        "status": "ready"
      }
    ]
  },
  {
    "id": "mail",
    "name": "mail",
    "pkg": "@platform-modules/mail",
    "layer": "L1",
    "status": "available",
    "verified": true,
    "tagline": "Transactional email with templating and provider failover, zero runtime deps.",
    "deps": [],
    "capabilities": [
      {
        "name": "templating",
        "kind": "capability",
        "desc": "Render templates with safe placeholder substitution.",
        "status": "ready"
      },
      {
        "name": "list-unsubscribe",
        "kind": "capability",
        "desc": "One-click unsubscribe headers (RFC 8058).",
        "status": "soon"
      },
      {
        "name": "suppression",
        "kind": "capability",
        "desc": "Suppression-list handling.",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "resend",
        "kind": "provider",
        "desc": "Resend delivery.",
        "status": "ready"
      },
      {
        "name": "ses",
        "kind": "provider",
        "desc": "Amazon SES delivery.",
        "status": "ready"
      },
      {
        "name": "postmark",
        "kind": "provider",
        "desc": "Postmark delivery.",
        "status": "ready"
      },
      {
        "name": "brevo",
        "kind": "provider",
        "desc": "Brevo delivery (no SDK, fetch-based).",
        "status": "ready"
      }
    ]
  },
  {
    "id": "auth",
    "name": "auth",
    "pkg": "@platform-modules/auth",
    "layer": "L1",
    "status": "available",
    "verified": true,
    "tagline": "Authentication, sessions and access methods — edge-native, no Node crypto.",
    "deps": [
      "util",
      "mail",
      "db"
    ],
    "capabilities": [
      {
        "name": "oauth",
        "kind": "capability",
        "desc": "Sign in with OAuth providers.",
        "status": "soon"
      },
      {
        "name": "oauth-provider",
        "kind": "capability",
        "desc": "Act as an OAuth authorization server (PKCE, consent).",
        "status": "soon"
      },
      {
        "name": "passkey",
        "kind": "capability",
        "desc": "Passkey / WebAuthn sign-in.",
        "status": "soon"
      },
      {
        "name": "otp-email",
        "kind": "capability",
        "desc": "Email one-time codes.",
        "status": "soon"
      },
      {
        "name": "totp",
        "kind": "capability",
        "desc": "Time-based authenticator codes (Web Crypto).",
        "status": "soon"
      },
      {
        "name": "admin-sessions",
        "kind": "capability",
        "desc": "Staff / admin session handling.",
        "status": "soon"
      },
      {
        "name": "portal-sessions",
        "kind": "capability",
        "desc": "Customer portal sessions.",
        "status": "soon"
      },
      {
        "name": "invites",
        "kind": "capability",
        "desc": "Team invitations.",
        "status": "soon"
      },
      {
        "name": "entitlements",
        "kind": "capability",
        "desc": "Gate features by plan tier.",
        "status": "soon"
      },
      {
        "name": "api-keys",
        "kind": "capability",
        "desc": "Issue, hash, rotate and scope API keys.",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "engine-custom",
        "kind": "provider",
        "desc": "Built-in engine — PBKDF2-SHA-512 with version-keyed peppering.",
        "status": "ready"
      },
      {
        "name": "engine-better-auth",
        "kind": "provider",
        "desc": "better-auth engine.",
        "status": "soon"
      },
      {
        "name": "otp-sms-firebase",
        "kind": "provider",
        "desc": "SMS one-time codes via Firebase.",
        "status": "soon"
      }
    ]
  },
  {
    "id": "tenancy",
    "name": "tenancy",
    "pkg": "@platform-modules/tenancy",
    "layer": "L1",
    "status": "available",
    "verified": true,
    "tagline": "Multi-tenant isolation and role-based access, enforced at the database.",
    "deps": [
      "db",
      "auth"
    ],
    "capabilities": [
      {
        "name": "domains",
        "kind": "capability",
        "desc": "Custom domains per tenant.",
        "status": "soon"
      },
      {
        "name": "usage-limits",
        "kind": "capability",
        "desc": "Per-tenant usage limits.",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "rbac-triad",
        "kind": "provider",
        "desc": "Role hierarchy — Owner / Admin / Member / Viewer / Contractor.",
        "status": "ready"
      },
      {
        "name": "rbac-flat",
        "kind": "provider",
        "desc": "Flat role enum.",
        "status": "ready"
      },
      {
        "name": "isolation-rls",
        "kind": "provider",
        "desc": "Postgres row-level security per tenant (structural).",
        "status": "ready"
      },
      {
        "name": "isolation-fk",
        "kind": "provider",
        "desc": "Foreign-key scoping (fail-closed).",
        "status": "ready"
      },
      {
        "name": "isolation-connection",
        "kind": "provider",
        "desc": "Per-tenant connection isolation.",
        "status": "soon"
      }
    ]
  },
  {
    "id": "ledger",
    "name": "ledger",
    "pkg": "@platform-modules/ledger",
    "layer": "L2",
    "status": "available",
    "tagline": "Append-only entries, guarded debits and materialized balances — no double-spend.",
    "deps": [
      "db"
    ],
    "capabilities": [
      {
        "name": "balances",
        "kind": "capability",
        "desc": "Idempotent entries, race-safe debits, materialized balance reads.",
        "status": "ready"
      },
      {
        "name": "vesting",
        "kind": "capability",
        "desc": "Time-vesting balances.",
        "status": "soon"
      },
      {
        "name": "lifetime",
        "kind": "capability",
        "desc": "Lifetime totals.",
        "status": "soon"
      },
      {
        "name": "balance-after",
        "kind": "capability",
        "desc": "Running balance recorded per entry.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "tax",
    "name": "tax",
    "pkg": "@platform-modules/tax",
    "layer": "L2",
    "status": "available",
    "tagline": "Exact integer VAT and sales-tax math, inclusive or exclusive.",
    "deps": [
      "db"
    ],
    "capabilities": [
      {
        "name": "rates-table",
        "kind": "capability",
        "desc": "VAT rate tables (Israel 1976–2025 + EU) with inclusive / exclusive math.",
        "status": "ready"
      },
      {
        "name": "vat-id",
        "kind": "capability",
        "desc": "VAT-ID validation.",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "stripe",
        "kind": "provider",
        "desc": "Stripe Tax.",
        "status": "soon"
      }
    ]
  },
  {
    "id": "notifications",
    "name": "notifications",
    "pkg": "@platform-modules/notifications",
    "layer": "L2",
    "status": "available",
    "verified": true,
    "tagline": "Multi-channel notifications with per-user preferences and dedup.",
    "deps": [
      "util"
    ],
    "capabilities": [
      {
        "name": "preferences",
        "kind": "capability",
        "desc": "Per-user opt-out and routing rules.",
        "status": "ready"
      }
    ],
    "providers": [
      {
        "name": "email",
        "kind": "provider",
        "desc": "Email channel (composes Mail).",
        "status": "ready"
      },
      {
        "name": "webpush",
        "kind": "provider",
        "desc": "Web push (VAPID, RFC 8291).",
        "status": "ready"
      },
      {
        "name": "telegram",
        "kind": "provider",
        "desc": "Telegram channel.",
        "status": "soon"
      },
      {
        "name": "sms",
        "kind": "provider",
        "desc": "SMS channel.",
        "status": "soon"
      },
      {
        "name": "in-app",
        "kind": "provider",
        "desc": "In-app inbox.",
        "status": "soon"
      }
    ]
  },
  {
    "id": "uploads",
    "name": "uploads",
    "pkg": "@platform-modules/uploads",
    "layer": "L2",
    "status": "available",
    "verified": true,
    "tagline": "Content-verified file uploads with presigned URLs and quotas.",
    "deps": [
      "util"
    ],
    "capabilities": [
      {
        "name": "magic-bytes",
        "kind": "capability",
        "desc": "Validate true file type by content (rejects spoofed / SVG / HTML).",
        "status": "ready"
      },
      {
        "name": "image-dimensions",
        "kind": "capability",
        "desc": "Read image dimensions.",
        "status": "ready"
      },
      {
        "name": "size-limit",
        "kind": "capability",
        "desc": "Enforce size limits.",
        "status": "ready"
      },
      {
        "name": "quota",
        "kind": "capability",
        "desc": "Per-account storage quotas.",
        "status": "ready"
      },
      {
        "name": "magic-bytes/audio",
        "kind": "capability",
        "desc": "Audio file-type detection.",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "presign-s3compat",
        "kind": "provider",
        "desc": "Presigned PUT for any S3-compatible store.",
        "status": "ready"
      },
      {
        "name": "r2-binding",
        "kind": "provider",
        "desc": "Cloudflare R2 binding.",
        "status": "ready"
      }
    ]
  },
  {
    "id": "search",
    "name": "search",
    "pkg": "@platform-modules/search",
    "layer": "L2",
    "status": "available",
    "tagline": "Register entity types, search across them with one paginated query.",
    "deps": [
      "db",
      "util"
    ],
    "capabilities": [
      {
        "name": "federation",
        "kind": "capability",
        "desc": "Federated full-text search over your own data, Postgres-native.",
        "status": "ready"
      },
      {
        "name": "external-engines",
        "kind": "capability",
        "desc": "Algolia / Meilisearch adapters.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "seo",
    "name": "seo",
    "pkg": "@platform-modules/seo",
    "layer": "L2",
    "status": "available",
    "tagline": "SEO primitives — structured data, sitemaps, canonicals, all XSS-hardened.",
    "deps": [],
    "capabilities": [
      {
        "name": "jsonld",
        "kind": "capability",
        "desc": "Safe JSON-LD structured data.",
        "status": "ready"
      },
      {
        "name": "sitemap",
        "kind": "capability",
        "desc": "Sitemap generation.",
        "status": "ready"
      },
      {
        "name": "gate",
        "kind": "capability",
        "desc": "Indexability rules and robots meta.",
        "status": "ready"
      },
      {
        "name": "canonical",
        "kind": "capability",
        "desc": "Canonical URL resolution.",
        "status": "ready"
      },
      {
        "name": "hreflang",
        "kind": "capability",
        "desc": "hreflang alternates for multilingual sites.",
        "status": "ready"
      },
      {
        "name": "robots",
        "kind": "capability",
        "desc": "robots.txt builder.",
        "status": "ready"
      }
    ],
    "providers": []
  },
  {
    "id": "ai",
    "name": "ai",
    "pkg": "@platform-modules/ai",
    "layer": "L2",
    "status": "available",
    "tagline": "Provider-agnostic LLM gateway with automatic fallback; cost stays in your hands.",
    "deps": [],
    "capabilities": [
      {
        "name": "usage",
        "kind": "capability",
        "desc": "Token-usage recording and daily rollups.",
        "status": "soon"
      },
      {
        "name": "tool-use",
        "kind": "capability",
        "desc": "Function / tool calling.",
        "status": "soon"
      },
      {
        "name": "model-discovery",
        "kind": "capability",
        "desc": "List available models with caching.",
        "status": "soon"
      },
      {
        "name": "job-runner",
        "kind": "capability",
        "desc": "Run AI jobs in the background (composes Jobs).",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "openai-compat",
        "kind": "provider",
        "desc": "OpenAI-compatible — OpenAI, Gemini-compat, Groq, Together.",
        "status": "ready"
      },
      {
        "name": "anthropic",
        "kind": "provider",
        "desc": "Anthropic Claude.",
        "status": "ready"
      },
      {
        "name": "google",
        "kind": "provider",
        "desc": "Google Generative AI.",
        "status": "soon"
      },
      {
        "name": "workers-ai",
        "kind": "provider",
        "desc": "Cloudflare Workers AI.",
        "status": "soon"
      }
    ]
  },
  {
    "id": "realtime",
    "name": "realtime",
    "pkg": "@platform-modules/realtime",
    "layer": "L2",
    "status": "available",
    "tagline": "Type-safe realtime events on Durable Objects with hibernatable WebSockets.",
    "deps": [],
    "capabilities": [
      {
        "name": "types",
        "kind": "capability",
        "desc": "Browser-safe event types shared client and server.",
        "status": "ready"
      },
      {
        "name": "server",
        "kind": "capability",
        "desc": "Server helpers — broadcast, hibernatable sockets, presence, queue consumers.",
        "status": "ready"
      }
    ],
    "providers": []
  },
  {
    "id": "billing",
    "name": "billing",
    "pkg": "@platform-modules/billing",
    "layer": "L2",
    "status": "available",
    "tagline": "Payments, subscriptions and refunds with exactly-once settlement.",
    "deps": [
      "db",
      "tax",
      "ledger"
    ],
    "capabilities": [
      {
        "name": "webhooks",
        "kind": "capability",
        "desc": "Verified webhook ingestion that owns its own response.",
        "status": "ready"
      },
      {
        "name": "subscriptions",
        "kind": "capability",
        "desc": "Recurring plans, upgrades, proration and dunning.",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "stripe",
        "kind": "provider",
        "desc": "Stripe — client-confirm, Connect splits, refunds.",
        "status": "ready"
      },
      {
        "name": "paypal",
        "kind": "provider",
        "desc": "PayPal.",
        "status": "soon"
      },
      {
        "name": "sumit",
        "kind": "provider",
        "desc": "Sumit — invoice-on-charge.",
        "status": "ready",
        "region": "IL"
      },
      {
        "name": "morning",
        "kind": "provider",
        "desc": "Morning (Greeninvoice).",
        "status": "soon",
        "region": "IL"
      },
      {
        "name": "payplus",
        "kind": "provider",
        "desc": "PayPlus.",
        "status": "soon",
        "region": "IL"
      },
      {
        "name": "cardcom",
        "kind": "provider",
        "desc": "Cardcom.",
        "status": "soon",
        "region": "IL"
      }
    ]
  },
  {
    "id": "entitlements",
    "name": "entitlements",
    "pkg": "@platform-modules/entitlements",
    "layer": "L2",
    "status": "design",
    "tagline": "Plan tiers, feature flags and usage quotas — gate any feature by what a customer's plan allows, free tiers included.",
    "deps": [
      "db",
      "util"
    ],
    "capabilities": [
      {
        "name": "tiers",
        "kind": "capability",
        "desc": "Map plans to the features and limits they unlock.",
        "status": "soon"
      },
      {
        "name": "feature-flags",
        "kind": "capability",
        "desc": "Turn features on by plan.",
        "status": "soon"
      },
      {
        "name": "quotas",
        "kind": "capability",
        "desc": "Usage quotas and metering.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "entitlements-react",
    "name": "entitlements-react",
    "pkg": "@platform-modules/entitlements-react",
    "layer": "L2",
    "status": "design",
    "sibling": "entitlements",
    "tagline": "React bindings for entitlements.",
    "deps": [
      "entitlements"
    ],
    "capabilities": [
      {
        "name": "useEntitlement",
        "kind": "capability",
        "desc": "Hook to check what the current plan allows.",
        "status": "soon"
      },
      {
        "name": "FeatureGate",
        "kind": "capability",
        "desc": "Component that shows children only when the plan allows.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "billing-react",
    "name": "billing-react",
    "pkg": "@platform-modules/billing-react",
    "layer": "L2",
    "status": "design",
    "sibling": "billing",
    "tagline": "React bindings for billing.",
    "deps": [
      "billing"
    ],
    "capabilities": [
      {
        "name": "PricingTable",
        "kind": "capability",
        "desc": "Plan comparison and pricing.",
        "status": "soon"
      },
      {
        "name": "BillingPortal",
        "kind": "capability",
        "desc": "Manage plan, payment method and invoices.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "marketing",
    "name": "marketing",
    "pkg": "@platform-modules/marketing",
    "layer": "L3",
    "status": "available",
    "tagline": "Email campaigns with compliance baked in — opt-in, suppression, ad-labels, consent.",
    "deps": [
      "mail"
    ],
    "capabilities": [
      {
        "name": "segments",
        "kind": "capability",
        "desc": "Audience segments.",
        "status": "ready"
      },
      {
        "name": "scheduling",
        "kind": "capability",
        "desc": "Schedule sends.",
        "status": "ready"
      },
      {
        "name": "automation",
        "kind": "capability",
        "desc": "Automated journeys.",
        "status": "ready"
      }
    ],
    "providers": [
      {
        "name": "self-managed",
        "kind": "provider",
        "desc": "Send through your own Mail setup.",
        "status": "ready"
      },
      {
        "name": "brevo",
        "kind": "provider",
        "desc": "Brevo (Sendinblue).",
        "status": "ready"
      },
      {
        "name": "loops",
        "kind": "provider",
        "desc": "Loops.",
        "status": "soon"
      }
    ]
  },
  {
    "id": "helpdesk",
    "name": "helpdesk",
    "pkg": "@platform-modules/helpdesk",
    "layer": "L3",
    "status": "available",
    "tagline": "Attach support to any entity — cases, threaded messages, attachments, SLAs.",
    "deps": [
      "db"
    ],
    "capabilities": [
      {
        "name": "messages",
        "kind": "capability",
        "desc": "Threaded, isolation-scoped messages.",
        "status": "ready"
      },
      {
        "name": "attachments",
        "kind": "capability",
        "desc": "Per-case attachments.",
        "status": "ready"
      },
      {
        "name": "transitions",
        "kind": "capability",
        "desc": "Append-only status transitions (audit trail).",
        "status": "ready"
      },
      {
        "name": "sla",
        "kind": "capability",
        "desc": "SLA timers — due and breach computation.",
        "status": "ready"
      },
      {
        "name": "email-intake",
        "kind": "capability",
        "desc": "Inbound email to cases.",
        "status": "soon"
      },
      {
        "name": "knowledge-base",
        "kind": "capability",
        "desc": "Self-serve knowledge base.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "audit",
    "name": "audit",
    "pkg": "@platform-modules/audit",
    "layer": "L2",
    "status": "available",
    "tagline": "Tamper-evident, append-only audit log that never breaks your writes.",
    "deps": [
      "db"
    ],
    "capabilities": [
      {
        "name": "append",
        "kind": "capability",
        "desc": "Append-only entries with keyset listing.",
        "status": "ready"
      },
      {
        "name": "diff",
        "kind": "capability",
        "desc": "Field-level change diffs.",
        "status": "soon"
      },
      {
        "name": "redact",
        "kind": "capability",
        "desc": "Redact sensitive fields.",
        "status": "soon"
      },
      {
        "name": "retention",
        "kind": "capability",
        "desc": "Retention and purge jobs.",
        "status": "soon"
      },
      {
        "name": "query",
        "kind": "capability",
        "desc": "Audit query and keyset paging.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "cache",
    "name": "cache",
    "pkg": "@platform-modules/cache",
    "layer": "L1",
    "status": "design",
    "tagline": "Pluggable caching with single-flight dedup, runtime-agnostic.",
    "deps": [],
    "capabilities": [
      {
        "name": "get-set",
        "kind": "capability",
        "desc": "get / set / getOrSet with single-flight.",
        "status": "soon"
      }
    ],
    "providers": [
      {
        "name": "memory",
        "kind": "provider",
        "desc": "In-memory (default).",
        "status": "soon"
      },
      {
        "name": "cf-kv",
        "kind": "provider",
        "desc": "Cloudflare KV.",
        "status": "soon"
      },
      {
        "name": "redis",
        "kind": "provider",
        "desc": "Redis.",
        "status": "soon"
      },
      {
        "name": "d1",
        "kind": "provider",
        "desc": "Cloudflare D1.",
        "status": "soon"
      }
    ]
  },
  {
    "id": "invoicing",
    "name": "invoicing",
    "pkg": "@platform-modules/invoicing",
    "layer": "L3",
    "status": "roadmap",
    "tagline": "Issue legal invoices and receipts through Israeli providers.",
    "deps": [
      "db"
    ],
    "capabilities": [],
    "providers": [
      {
        "name": "morning",
        "kind": "provider",
        "desc": "Morning invoices.",
        "status": "soon",
        "region": "IL"
      },
      {
        "name": "icount",
        "kind": "provider",
        "desc": "iCount invoices.",
        "status": "soon",
        "region": "IL"
      },
      {
        "name": "rivhit",
        "kind": "provider",
        "desc": "Rivhit invoices.",
        "status": "soon",
        "region": "IL"
      },
      {
        "name": "invoice4u",
        "kind": "provider",
        "desc": "Invoice4U invoices.",
        "status": "soon",
        "region": "IL"
      },
      {
        "name": "easycount",
        "kind": "provider",
        "desc": "EasyCount invoices.",
        "status": "soon",
        "region": "IL"
      }
    ]
  },
  {
    "id": "affiliate",
    "name": "affiliate",
    "pkg": "@platform-modules/affiliate",
    "layer": "L3",
    "status": "roadmap",
    "tagline": "Referral tracking and commission payouts.",
    "deps": [
      "db",
      "ledger"
    ],
    "capabilities": [
      {
        "name": "referrals",
        "kind": "capability",
        "desc": "Track referrals and earn-gated commissions.",
        "status": "soon"
      },
      {
        "name": "fraud",
        "kind": "capability",
        "desc": "Fraud detection.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "content",
    "name": "content",
    "pkg": "@platform-modules/content",
    "layer": "L2",
    "status": "available",
    "tagline": "Posts, pages, taxonomy and feeds — the content engine behind Blog and CMS.",
    "deps": [
      "db"
    ],
    "capabilities": [
      {
        "name": "entries",
        "kind": "capability",
        "desc": "Create and manage posts and pages.",
        "status": "soon"
      },
      {
        "name": "draft-publish",
        "kind": "capability",
        "desc": "Draft / publish workflow with scheduling.",
        "status": "soon"
      },
      {
        "name": "taxonomy",
        "kind": "capability",
        "desc": "Categories, tags and custom taxonomies.",
        "status": "soon"
      },
      {
        "name": "rss-feed",
        "kind": "capability",
        "desc": "RSS / Atom feed generation.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "content-react",
    "name": "content-react",
    "pkg": "@platform-modules/content-react",
    "layer": "L2",
    "status": "roadmap",
    "sibling": "content",
    "tagline": "React bindings for content.",
    "deps": [
      "content"
    ],
    "capabilities": [
      {
        "name": "useEntries",
        "kind": "capability",
        "desc": "Hook for fetching content entries.",
        "status": "soon"
      },
      {
        "name": "EntryList",
        "kind": "capability",
        "desc": "Rendered list component for posts and pages.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "helpdesk-react",
    "name": "helpdesk-react",
    "pkg": "@platform-modules/helpdesk-react",
    "layer": "L3",
    "status": "design",
    "sibling": "helpdesk",
    "tagline": "React bindings for helpdesk.",
    "deps": [
      "helpdesk"
    ],
    "capabilities": [
      {
        "name": "TicketList",
        "kind": "capability",
        "desc": "Rendered list of support tickets.",
        "status": "soon"
      },
      {
        "name": "ThreadView",
        "kind": "capability",
        "desc": "Threaded conversation view.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "marketing-react",
    "name": "marketing-react",
    "pkg": "@platform-modules/marketing-react",
    "layer": "L3",
    "status": "design",
    "sibling": "marketing",
    "tagline": "React bindings for marketing.",
    "deps": [
      "marketing"
    ],
    "capabilities": [
      {
        "name": "SignupForm",
        "kind": "capability",
        "desc": "Newsletter signup form component.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "i18n",
    "name": "i18n",
    "pkg": "@platform-modules/i18n",
    "layer": "L0",
    "status": "available",
    "tagline": "Internationalization, framework-free and browser-safe.",
    "deps": [],
    "capabilities": [
      {
        "name": "rtl",
        "kind": "capability",
        "desc": "Right-to-left direction handling.",
        "status": "ready"
      },
      {
        "name": "format",
        "kind": "capability",
        "desc": "Locale-aware number and date formatting.",
        "status": "ready"
      },
      {
        "name": "plural",
        "kind": "capability",
        "desc": "Pluralization rules.",
        "status": "ready"
      },
      {
        "name": "routing",
        "kind": "capability",
        "desc": "Locale routing.",
        "status": "ready"
      },
      {
        "name": "loader",
        "kind": "capability",
        "desc": "Lazy-load translation bundles.",
        "status": "soon"
      },
      {
        "name": "pick",
        "kind": "capability",
        "desc": "Pick a localized database field by locale.",
        "status": "soon"
      },
      {
        "name": "zod",
        "kind": "capability",
        "desc": "Localized validation messages.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "i18n-react",
    "name": "i18n-react",
    "pkg": "@platform-modules/i18n-react",
    "layer": "L0",
    "status": "available",
    "sibling": "i18n",
    "tagline": "React bindings for i18n.",
    "deps": [
      "i18n"
    ],
    "capabilities": [
      {
        "name": "I18nProvider",
        "kind": "capability",
        "desc": "Context provider for translations.",
        "status": "ready"
      },
      {
        "name": "useTranslations",
        "kind": "capability",
        "desc": "Hook for translated strings.",
        "status": "ready"
      },
      {
        "name": "useLocale",
        "kind": "capability",
        "desc": "Hook for the active locale.",
        "status": "ready"
      },
      {
        "name": "LanguageSwitcher",
        "kind": "capability",
        "desc": "Drop-in language switcher component.",
        "status": "ready"
      }
    ],
    "providers": []
  },
  {
    "id": "realtime-react",
    "name": "realtime-react",
    "pkg": "@platform-modules/realtime-react",
    "layer": "L2",
    "status": "available",
    "sibling": "realtime",
    "tagline": "React bindings for realtime.",
    "deps": [
      "realtime"
    ],
    "capabilities": [
      {
        "name": "useChannel",
        "kind": "capability",
        "desc": "Subscribe to a realtime channel.",
        "status": "ready"
      },
      {
        "name": "usePresence",
        "kind": "capability",
        "desc": "Track who is online.",
        "status": "ready"
      },
      {
        "name": "Channel",
        "kind": "capability",
        "desc": "Declarative channel component.",
        "status": "ready"
      }
    ],
    "providers": []
  },
  {
    "id": "ui-tokens",
    "name": "ui-tokens",
    "pkg": "@platform-modules/ui-tokens",
    "layer": "UI",
    "status": "design",
    "tagline": "Design tokens as a typed contract — one theme drives every component.",
    "deps": [],
    "capabilities": [
      {
        "name": "colors",
        "kind": "capability",
        "desc": "Semantic color roles — foreground, accent, danger, success.",
        "status": "soon"
      },
      {
        "name": "spacing",
        "kind": "capability",
        "desc": "A spacing scale, never raw pixels.",
        "status": "soon"
      },
      {
        "name": "radius",
        "kind": "capability",
        "desc": "Corner-radius scale.",
        "status": "soon"
      },
      {
        "name": "typography",
        "kind": "capability",
        "desc": "Font-size and weight scale.",
        "status": "soon"
      },
      {
        "name": "theme",
        "kind": "capability",
        "desc": "Swap the whole theme without touching a single component.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "ui-util",
    "name": "ui-util",
    "pkg": "@platform-modules/ui-util",
    "layer": "UI",
    "status": "roadmap",
    "tagline": "The small UI helpers every component package needs.",
    "deps": [
      "ui-tokens"
    ],
    "capabilities": [
      {
        "name": "class-merge",
        "kind": "capability",
        "desc": "Merge component and token classes without conflicts.",
        "status": "soon"
      },
      {
        "name": "variants",
        "kind": "capability",
        "desc": "Build typed component variants.",
        "status": "soon"
      },
      {
        "name": "direction",
        "kind": "capability",
        "desc": "Right-to-left aware helpers.",
        "status": "soon"
      },
      {
        "name": "focus",
        "kind": "capability",
        "desc": "Focus-ring and visually-hidden utilities.",
        "status": "soon"
      }
    ],
    "providers": []
  },
  {
    "id": "ui-primitives",
    "name": "ui-primitives",
    "pkg": "@platform-modules/ui-primitives",
    "layer": "UI",
    "status": "roadmap",
    "tagline": "Accessible React components, built on Radix and styled from the tokens.",
    "deps": [
      "ui-tokens",
      "ui-util"
    ],
    "capabilities": [
      {
        "name": "Button",
        "kind": "capability",
        "desc": "Button with variants and sizes from the token scale.",
        "status": "soon"
      },
      {
        "name": "Dialog",
        "kind": "capability",
        "desc": "Modal dialog with focus trap and escape handling.",
        "status": "soon"
      },
      {
        "name": "Table",
        "kind": "capability",
        "desc": "Sortable, accessible data table.",
        "status": "soon"
      },
      {
        "name": "Tabs",
        "kind": "capability",
        "desc": "Keyboard-navigable tabs.",
        "status": "soon"
      },
      {
        "name": "Toast",
        "kind": "capability",
        "desc": "Announced, dismissible toasts.",
        "status": "soon"
      },
      {
        "name": "Select",
        "kind": "capability",
        "desc": "Typeahead-friendly select.",
        "status": "soon"
      },
      {
        "name": "Menu",
        "kind": "capability",
        "desc": "Roving-focus menu and dropdowns.",
        "status": "soon"
      },
      {
        "name": "Checkbox",
        "kind": "capability",
        "desc": "Checkbox and radio with proper labelling.",
        "status": "soon"
      }
    ],
    "providers": []
  }
];

export const blueprints: Blueprint[] = [
  {
    "id": "bp-saas-admin",
    "kind": "blueprint",
    "name": "SaaS admin",
    "status": "coming",
    "tagline": "Multi-tenant SaaS back-office with accounts, teams, billing and admin.",
    "presets": [
      "saas"
    ],
    "plugins": [
      "subscriptions"
    ],
    "deps": [
      "tpl-auth",
      "tpl-account",
      "tpl-team-org",
      "tpl-admin-dashboard",
      "tpl-onboarding",
      "tpl-subscription-tiers"
    ],
    "modules": [
      "util",
      "db",
      "auth",
      "tenancy",
      "mail",
      "jobs",
      "tax",
      "ledger",
      "billing",
      "audit"
    ]
  },
  {
    "id": "bp-saas-b2b",
    "kind": "blueprint",
    "name": "SaaS B2B",
    "status": "coming",
    "tagline": "Multi-tenant B2B SaaS with deeper roles and org switching.",
    "presets": [
      "saas"
    ],
    "plugins": [
      "subscriptions"
    ],
    "deps": [
      "tpl-auth",
      "tpl-account",
      "tpl-team-org",
      "tpl-admin-dashboard",
      "tpl-subscription-tiers"
    ],
    "modules": [
      "util",
      "db",
      "auth",
      "tenancy",
      "mail",
      "jobs",
      "tax",
      "ledger",
      "billing",
      "audit"
    ]
  },
  {
    "id": "bp-commerce-storefront",
    "kind": "blueprint",
    "name": "Commerce storefront",
    "status": "coming",
    "tagline": "Online store with catalogue pages, admin and subscribe-and-save.",
    "presets": [
      "commerce"
    ],
    "plugins": [
      "subscriptions"
    ],
    "deps": [
      "tpl-content",
      "tpl-admin-dashboard"
    ],
    "modules": [
      "util",
      "db",
      "billing",
      "tax",
      "ledger",
      "uploads",
      "search"
    ]
  },
  {
    "id": "bp-community-forum",
    "kind": "blueprint",
    "name": "Community forum",
    "status": "coming",
    "tagline": "Forum or community site with accounts, content, moderation and realtime.",
    "presets": [
      "community"
    ],
    "plugins": [],
    "deps": [
      "tpl-auth",
      "tpl-content",
      "tpl-moderation",
      "tpl-notifications",
      "tpl-onboarding"
    ],
    "modules": [
      "util",
      "db",
      "mail",
      "auth",
      "realtime",
      "notifications",
      "search",
      "uploads",
      "audit"
    ]
  },
  {
    "id": "bp-blog",
    "kind": "blueprint",
    "name": "Blog",
    "status": "coming",
    "tagline": "Publishing site with posts, pages, feeds and a marketing front.",
    "presets": [
      "core"
    ],
    "plugins": [
      "blog"
    ],
    "deps": [
      "tpl-auth",
      "tpl-content",
      "tpl-marketing"
    ],
    "modules": [
      "util",
      "db",
      "auth",
      "mail"
    ]
  },
  {
    "id": "bp-cms",
    "kind": "blueprint",
    "name": "CMS",
    "status": "coming",
    "tagline": "Host-agnostic content management, editors and roles.",
    "presets": [
      "core"
    ],
    "plugins": [
      "cms"
    ],
    "deps": [
      "tpl-content",
      "tpl-admin-dashboard",
      "tpl-team-org"
    ],
    "modules": [
      "util",
      "db",
      "auth",
      "mail"
    ]
  },
  {
    "id": "bp-ai-saas",
    "kind": "blueprint",
    "name": "AI SaaS",
    "status": "coming",
    "tagline": "AI product with usage-metered plans and an admin.",
    "presets": [
      "saas"
    ],
    "plugins": [
      "subscriptions"
    ],
    "deps": [
      "tpl-auth",
      "tpl-account",
      "tpl-subscription-tiers"
    ],
    "modules": [
      "util",
      "db",
      "auth",
      "tenancy",
      "mail",
      "jobs",
      "tax",
      "ledger",
      "billing",
      "audit"
    ]
  },
  {
    "id": "bp-marketing-site",
    "kind": "blueprint",
    "name": "Marketing site",
    "status": "coming",
    "tagline": "Landing site with marketing capture and a blog.",
    "presets": [
      "core"
    ],
    "plugins": [
      "marketing",
      "blog"
    ],
    "deps": [
      "tpl-marketing",
      "tpl-content"
    ],
    "modules": [
      "util",
      "db",
      "auth",
      "mail"
    ]
  },
  {
    "id": "bp-helpdesk",
    "kind": "blueprint",
    "name": "Helpdesk",
    "status": "coming",
    "tagline": "Support desk with tickets, admin and notifications.",
    "presets": [
      "core"
    ],
    "plugins": [
      "helpdesk"
    ],
    "deps": [
      "tpl-auth",
      "tpl-admin-dashboard",
      "tpl-notifications"
    ],
    "modules": [
      "util",
      "db",
      "auth",
      "mail"
    ]
  }
];

const moduleById = new Map(modules.map((m) => [m.id, m]));

export function getModule(id: string): Module | undefined {
  return moduleById.get(id);
}

export function getBlueprint(id: string): Blueprint | undefined {
  return blueprints.find((b) => b.id === id);
}

/** The module plus its transitive dependencies (deps-first order, deduped). */
export function depClosure(moduleId: string): string[] {
  const out: string[] = [];
  const seen = new Set<string>();
  function walk(id: string) {
    if (seen.has(id)) return;
    seen.add(id);
    const mod = moduleById.get(id);
    if (!mod) return;
    for (const dep of mod.deps) walk(dep);
    out.push(id);
  }
  walk(moduleId);
  return out;
}

/** Modules used by mod-cms marketing site. */
export const MOD_CMS_MODULES = ['content', 'db', 'auth', 'seo', 'uploads'] as const;
export type ModCmsModuleId = (typeof MOD_CMS_MODULES)[number];
