{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://resource.rahmanef.com/slice-schema.json",
  "title": "Rahman Resources slice.json",
  "description": "Contract for a tier-3 portable feature slice. See docs/slice-architecture.md.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "slug",
    "version",
    "category",
    "title",
    "description",
    "namespace",
    "frontend",
    "deps"
  ],
  "properties": {
    "$schema": {
      "type": "string"
    },
    "slug": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$",
      "description": "Globally-unique kebab-case id."
    },
    "version": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$",
      "description": "Slice semver, independent of kitab version."
    },
    "category": {
      "type": "string",
      "enum": [
        "ai",
        "auth",
        "data",
        "integrations",
        "content",
        "ui",
        "os",
        "infra"
      ]
    },
    "kind": {
      "type": "string",
      "enum": [
        "ui",
        "backend",
        "full"
      ],
      "description": "Slice shape \u2014 ui (no convex), backend (no UI), full (both)."
    },
    "variants": {
      "type": "object",
      "additionalProperties": false,
      "required": ["default", "items"],
      "description": "shadcn-style variants. Each item's files live at variants/<id>/; an optional shared/ folder is copied for every variant. `npx rr add <slug> <id>` installs one variant (flattened to slice root); `npx rr add <slug>` installs all + a root index.ts switcher selected via a `variant` prop.",
      "properties": {
        "default": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]*$",
          "description": "Fallback variant id for the all-mode switcher. Must be one of items[].id."
        },
        "shared": {
          "type": "string",
          "description": "Folder (relative to slice root) copied for every variant. Omit if variants are self-contained."
        },
        "items": {
          "type": "array",
          "minItems": 2,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id"],
            "properties": {
              "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
              "title": { "type": "string" },
              "description": { "type": "string" },
              "convex": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Convex root paths for THIS variant. When installing this variant the CLI pulls only these (not the slice-level union). Should be a subset of convex.rootPaths."
              }
            }
          }
        }
      }
    },
    "title": {
      "type": "string",
      "minLength": 3
    },
    "description": {
      "type": "string",
      "minLength": 10
    },
    "namespace": {
      "type": "string",
      "pattern": "^@/features/[a-z0-9][a-z0-9-]*$",
      "description": "Import root for slice-internal references; CLI rewrites if user opts a different namespace."
    },
    "convex": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "tablesExport": {
          "type": "string",
          "pattern": "^([a-zA-Z][a-zA-Z0-9_]*)?$",
          "description": "Name of the table-fragment export in schema.ts (e.g., midtransTables). Empty for ui-only slices."
        },
        "schemaPath": {
          "type": "string",
          "description": "Convex schema file inside this slice's convex tree."
        },
        "rootPaths": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Convex folders the lift pulls into the consumer's convex/. Empty for ui-only slices."
        }
      }
    },
    "frontend": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "slicePath"
      ],
      "properties": {
        "slicePath": {
          "type": "string",
          "pattern": "^(template-base/)?frontend/slices/[a-z0-9_/-]+$",
          "description": "Portable home \u2192 frontend/slices/<slug>. Foundation home \u2192 template-base/frontend/slices/<slug>."
        },
        "configExport": {
          "type": "string",
          "pattern": "^([a-zA-Z][a-zA-Z0-9_]*)?$",
          "description": "Name of the defineFeature(...) export the registry generators look for. Empty for ui-only slices."
        }
      }
    },
    "deps": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "npm": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Plain npm install lines."
        },
        "shadcn": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "shadcn primitives this slice imports."
        },
        "env": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "name",
              "scope"
            ],
            "properties": {
              "name": {
                "type": "string",
                "pattern": "^[A-Z][A-Z0-9_]*$"
              },
              "scope": {
                "type": "string",
                "enum": [
                  "convex",
                  "next-public",
                  "server"
                ]
              },
              "required": {
                "type": "boolean",
                "default": true
              },
              "description": {
                "type": "string"
              }
            }
          }
        },
        "peers": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "slug",
              "range"
            ],
            "properties": {
              "slug": {
                "type": "string"
              },
              "range": {
                "type": "string"
              },
              "optional": {
                "type": "boolean",
                "description": "Peer is optional — slice degrades gracefully without it (e.g. a swappable payment provider)."
              },
              "reason": {
                "type": "string"
              }
            }
          }
        },
        "sharedFiles": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Repo-root shared files (relative to project root) this slice imports \u2014 the CLI copies them alongside the slice on add."
        }
      }
    },
    "registers": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "registry",
          "preview-registry",
          "export-registry"
        ]
      },
      "description": "Which registry generators auto-discover this slice."
    },
    "audit": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^bp:[a-z0-9-]+$"
      },
      "description": "Audit-bp rule ids that apply to this slice."
    },
    "license": {
      "type": "string",
      "default": "MIT"
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "providers": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Optional sub-provider list when a slice routes between alternatives (e.g., payment slice with midtrans + doku siblings)."
    },
    "previews": {
      "type": "array",
      "description": "Variant-preview declarations (VP wave). Each entry maps a public component to either enum variant axes (leaf slices) or scenario presets (subsystem slices). Rendered by frontend/slices/<slug>/preview.tsx \u2014 rr-internal, stripped on `rr add`. See docs/SLICE-PREVIEW-SPEC.md.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "component",
          "kind"
        ],
        "properties": {
          "component": {
            "type": "string",
            "pattern": "^[A-Z][A-Za-z0-9]*$",
            "description": "Public component export this preview renders."
          },
          "kind": {
            "type": "string",
            "enum": [
              "variants",
              "scenarios"
            ],
            "description": "variants = enum prop axes (leaf); scenarios = curated presets (subsystem)."
          },
          "axes": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "prop",
                "values"
              ],
              "properties": {
                "prop": {
                  "type": "string",
                  "pattern": "^[a-z][A-Za-z0-9]*$"
                },
                "values": {
                  "type": "array",
                  "minItems": 1,
                  "items": {
                    "type": "string"
                  }
                },
                "default": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              }
            },
            "description": "Enum-only variant axes (max 3 \u2014 enforced by gen-preview-registry). preview.tsx maps value strings to real props."
          },
          "scenarios": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^[a-z0-9][a-z0-9-]*$"
                },
                "title": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              }
            },
            "description": "Curated preset configurations for subsystem slices."
          },
          "seed": {
            "type": "string",
            "description": "Human note describing the localStorage demo data (actual seed lives in preview.tsx)."
          }
        }
      }
    },
    "deprecated": {
      "type": "string",
      "description": "Successor slug. This slice was merged into the named slice as variants; install resolves there via manifest.aliases."
    },
    "contract": {
      "type": "object",
      "description": "Folded Phase-A composition contract (Phase 2 hybrid fold, 2026-06-21): requires/provides/conflicts/migrationFrom/generalization moved from slice.contract.ts. id+version omitted (== slug/version). requires.deps is verbatim pending per-slice normalization, so this is intentionally loose; strict invariants move to validate-slice when the .ts is retired."
    }
  }
}
