// @bun
var A=Object.defineProperty;var S=(m)=>m;function P(m,u){this[m]=S.bind(null,u)}var V=(m,u)=>{for(var v in u)A(m,v,{get:u[v],enumerable:!0,configurable:!0,set:P.bind(u,v)})};var W=(m,u)=>()=>(m&&(u=m(m=0)),u);import{CodeBlock as h}from"@contractspec/lib.design-system";import w from"@contractspec/lib.ui-link";import{ChevronRight as _}from"lucide-react";import{jsx as n,jsxs as r}from"react/jsx-runtime";function T(){return r("div",{className:"space-y-8",children:[r("div",{className:"space-y-4",children:[n("h1",{className:"font-bold text-4xl",children:"App Configuration"}),n("p",{className:"text-muted-foreground",children:"ContractSpec uses a three-tier configuration model that separates global app definitions from tenant-specific settings and runtime resolution."})]}),r("div",{className:"space-y-4",children:[n("h2",{className:"font-bold text-2xl",children:"AppBlueprintSpec"}),r("p",{className:"text-muted-foreground",children:["The ",n("strong",{children:"AppBlueprintSpec"})," is the global, versioned definition of your application. It contains no tenant-specific information and is stored in version control."]}),n(h,{language:"typescript",code:`type AppBlueprintSpec = {
  id: string;
  version: string;
  name: string;
  description: string;
  
  // Core specs
  capabilities: CapabilitySpec[];
  dataViews: DataViewSpec[];
  workflows: WorkflowSpec[];
  policies: PolicySpec[];
  
  // Required integrations
  requiredIntegrations: {
    integrationId: string;
    category: IntegrationCategory;
    purpose: string;
    optional?: boolean;
  }[];
  
  // Expected knowledge spaces
  knowledgeSpaces: {
    spaceId: string;
    category: KnowledgeCategory;
    required: boolean;
    purpose: string;
  }[];
  
  // UI/UX
  theme: ThemeSpec;
  overlays: OverlaySpec[];
  
  // Observability
  telemetry: TelemetrySpec;
  
  // Schema evolution
  migrations: MigrationSpec[];
};`})]}),r("div",{className:"space-y-4",children:[n("h2",{className:"font-bold text-2xl",children:"TenantAppConfig"}),r("p",{className:"text-muted-foreground",children:["The ",n("strong",{children:"TenantAppConfig"})," is the per-tenant, per-environment configuration that customizes how a specific tenant uses the app."]}),n(h,{language:"typescript",code:`type TenantAppConfig = {
  tenantId: string;
  blueprintId: string;
  blueprintVersion: string;
  environment: "sandbox" | "staging" | "production";
  status: "draft" | "preview" | "published" | "archived" | "superseded";
  
  // Integration bindings
  integrationBindings: AppIntegrationBinding[];
  
  // Knowledge bindings
  knowledgeBindings: AppKnowledgeBinding[];
  
  // Tenant-specific overrides
  featureFlags: Record<string, boolean>;
  limits: {
    maxUsers?: number;
    maxStorage?: number;
    rateLimit?: number;
  };
  
  // Tenant customization
  branding: {
    logo?: string;
    colors?: Record<string, string>;
    domain?: string;
  };
  
  metadata: Record<string, unknown>;
  createdAt: string;
  updatedAt: string;
};`})]}),r("div",{className:"space-y-4",children:[n("h2",{className:"font-bold text-2xl",children:"AppIntegrationBinding"}),n("p",{className:"text-muted-foreground",children:"Defines how a tenant connects specific integration instances to satisfy capabilities and workflows."}),n(h,{language:"typescript",code:`type AppIntegrationBinding = {
  slotId: string;          // References AppIntegrationSlot.slotId
  connectionId: string;    // References IntegrationConnection.meta.id
  scope?: {
    workflows?: string[];
    operations?: string[];
    features?: string[];
  };
  priority?: number;       // Lower number = higher priority
};

// Example:
{
  slotId: "payments.primary",
  connectionId: "conn_stripe_acme_prod",
  scope: {
    workflows: ["checkout", "subscription-renewal"],
    operations: ["payments.stripe.*"]
  },
  priority: 1
}`})]}),r("div",{className:"space-y-4",children:[n("h2",{className:"font-bold text-2xl",children:"AppKnowledgeBinding"}),n("p",{className:"text-muted-foreground",children:"Defines which knowledge spaces a tenant's app can access and how."}),n(h,{language:"typescript",code:`type AppKnowledgeBinding = {
  spaceId: string;
  enabled: boolean;
  
  // Which workflows/agents can read this space
  allowedConsumers: {
    workflowIds?: string[];
    agentIds?: string[];
    roles?: string[];
  };
  
  // Category-based access control
  allowedCategories: KnowledgeCategory[];
  
  // Sources feeding this space for this tenant
  sources: string[];  // References KnowledgeSourceConfig IDs
  
  metadata?: Record<string, unknown>;
};

// Example:
{
  spaceId: "product-canon",
  enabled: true,
  allowedConsumers: {
    workflowIds: ["invoice-generation", "quote-creation"],
    agentIds: ["support-agent"]
  },
  allowedCategories: ["canonical", "operational"],
  sources: ["src_notion_product_docs", "src_database_schema"]
}`})]}),r("div",{className:"space-y-4",children:[n("h2",{className:"font-bold text-2xl",children:"ResolvedAppConfig"}),r("p",{className:"text-muted-foreground",children:["The ",n("strong",{children:"ResolvedAppConfig"})," is the runtime result of merging AppBlueprintSpec with TenantAppConfig. It's computed on-demand and never persisted."]}),n(h,{language:"typescript",code:`type ResolvedAppConfig = {
  appId: string;
  tenantId: string;
  blueprintName: string;
  blueprintVersion: number;
  environment?: string;
  configVersion: number;

  capabilities: { enabled: CapabilityRef[]; disabled: CapabilityRef[] };
  features: { include: FeatureRef[]; exclude: FeatureRef[] };
  dataViews: Record<string, SpecPointer>;
  workflows: Record<string, SpecPointer>;
  policies: PolicyRef[];
  theme?: AppThemeBinding;
  telemetry?: TelemetryBinding;
  experiments: {
    catalog: ExperimentRef[];
    active: ExperimentRef[];
    paused: ExperimentRef[];
  };
  featureFlags: FeatureFlagState[];
  routes: AppRouteConfig[];

  integrations: ResolvedIntegration[]; // [{ slot, binding, connection, spec }]
  knowledge: ResolvedKnowledge[];       // [{ binding, space, sources }]
  branding: ResolvedBranding;           // { appName, assets, colors, domain }
  notes?: string;
};`})]}),r("div",{className:"space-y-4",children:[n("h2",{className:"font-bold text-2xl",children:"Configuration flow"}),n("p",{className:"text-muted-foreground",children:"Here's how configuration flows from definition to runtime:"}),r("ol",{className:"list-inside list-decimal space-y-3 text-muted-foreground",children:[r("li",{children:[n("strong",{children:"Development"})," - Define AppBlueprintSpec with required integrations and knowledge spaces"]}),r("li",{children:[n("strong",{children:"Deployment"})," - Deploy blueprint to environment (sandbox, staging, production)"]}),r("li",{children:[n("strong",{children:"Tenant Setup"})," - Create TenantAppConfig with specific integration connections and knowledge sources"]}),r("li",{children:[n("strong",{children:"Runtime"})," - Resolve configuration on-demand when tenant accesses the app"]}),r("li",{children:[n("strong",{children:"Execution"})," - Use ResolvedAppConfig to execute capabilities, workflows, and enforce policies"]})]})]}),r("div",{className:"space-y-4",children:[n("h2",{className:"font-bold text-2xl",children:"Best practices"}),r("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[n("li",{children:"Keep AppBlueprintSpec environment-agnostic - no secrets or tenant-specific data"}),n("li",{children:"Use TenantAppConfig for all tenant-specific settings and connections"}),n("li",{children:"Cache ResolvedAppConfig per request to avoid repeated resolution"}),n("li",{children:"Version blueprints carefully - migrations affect all tenants"}),n("li",{children:"Test blueprint changes in sandbox before promoting to production"})]})]}),r("div",{className:"flex items-center gap-4 pt-4",children:[n(w,{href:"/docs/architecture",className:"btn-ghost",children:"Back to Architecture"}),r(w,{href:"/docs/architecture/integration-binding",className:"btn-primary",children:["Integration Binding ",n(_,{size:16})]})]})]})}import{CodeBlock as N}from"@contractspec/lib.design-system";import b from"@contractspec/lib.ui-link";import{ChevronRight as B}from"lucide-react";import{jsx as o,jsxs as p}from"react/jsx-runtime";function R(){return p("div",{className:"space-y-8",children:[p("div",{className:"space-y-4",children:[o("h1",{className:"font-bold text-4xl",children:"Control Plane Runtime"}),o("p",{className:"text-muted-foreground",children:"The control plane is the governance layer for agentic execution. It turns incoming intent into deterministic plans, enforces risk policy before side effects, and records replayable traces for audits."})]}),p("div",{className:"space-y-4",children:[o("h2",{className:"font-bold text-2xl",children:"Canonical execution loop"}),p("ol",{className:"list-inside list-decimal space-y-2 text-muted-foreground",children:[o("li",{children:"Accept intent and create execution identity + trace context."}),o("li",{children:"Compile intent into a typed, deterministic plan DAG."}),o("li",{children:"Verify plan against policy and risk rules."}),o("li",{children:"Route into autonomous or assist mode based on verdict."}),o("li",{children:"Execute steps with idempotent keys and explicit stage events."}),o("li",{children:"Persist outcomes for replay, audits, and operator visibility."})]})]}),p("div",{className:"space-y-4",children:[o("h2",{className:"font-bold text-2xl",children:"Contract surfaces (v1 baseline)"}),p("p",{className:"text-muted-foreground",children:["The runtime is contract-first. Commands, queries, events, and capabilities are explicit and versioned under",o("code",{children:" @contractspec/lib.contracts-spec"}),"."]}),o(N,{language:"text",code:`Commands
- controlPlane.intent.submit
- controlPlane.plan.compile
- controlPlane.plan.verify
- controlPlane.execution.start
- controlPlane.execution.approve
- controlPlane.execution.reject
- controlPlane.execution.cancel
- controlPlane.skill.install
- controlPlane.skill.disable

Queries
- controlPlane.execution.get
- controlPlane.execution.list
- controlPlane.trace.get
- controlPlane.policy.explain
- controlPlane.skill.list
- controlPlane.skill.verify

Events
- controlPlane.intent.received
- controlPlane.plan.compiled
- controlPlane.plan.rejected
- controlPlane.execution.step.started
- controlPlane.execution.step.blocked
- controlPlane.execution.step.completed
- controlPlane.execution.completed
- controlPlane.execution.failed
- controlPlane.skill.installed
- controlPlane.skill.rejected

Capabilities
- control-plane.core
- control-plane.approval
- control-plane.audit
- control-plane.skill-registry
- control-plane.channel-runtime`})]}),p("div",{className:"space-y-4",children:[o("h2",{className:"font-bold text-2xl",children:"Policy and safety posture"}),p("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[o("li",{children:"No side-effect action executes unless it comes from a compiled plan."}),o("li",{children:"High-risk actions are blocked from autonomous mode in v1."}),o("li",{children:"Approval commands provide explicit human-in-the-loop transitions."}),o("li",{children:"Skill installation is modeled as governance-controlled operations."}),o("li",{children:"Trace queries expose policy rationale and step outcomes for replay."})]})]}),p("section",{className:"editorial-panel space-y-4",children:[o("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"Apply the runtime locally with Connect"}),o("p",{className:"text-muted-foreground text-sm leading-7",children:"The control plane defines the governance contracts. Connect is the local adapter that turns those contracts into task-scoped context, plan, verification, review, and replay flows for coding agents."}),p("div",{className:"flex flex-wrap gap-3",children:[o(b,{href:"/docs/specs/connect",className:"btn-primary",children:"Connect spec"}),o(b,{href:"/docs/guides/connect-in-a-repo",className:"btn-ghost",children:"Use Connect in a repo"})]})]}),p("div",{className:"space-y-4",children:[o("h2",{className:"font-bold text-2xl",children:"Implementation map"}),o(N,{language:"text",code:`packages/libs/contracts-spec/src/control-plane/
  commands/
  queries/
  events/
  capabilities/
  contracts.ts
  contracts.test.ts

packages/apps/web-landing/src/app/docs/architecture/control-plane/page.tsx
implementation_plan_controle_plane.md`})]}),p("div",{className:"space-y-4",children:[o("h2",{className:"font-bold text-2xl",children:"What comes next"}),o("p",{className:"text-muted-foreground",children:"WS1 delivers the contract fabric. Next increments add planner/executor split, policy escalation, capability-bound authorization, signed skill compatibility checks, and full replay tooling."})]}),p("div",{className:"flex items-center gap-4 pt-4",children:[o(b,{href:"/docs/architecture/integration-binding",className:"btn-ghost",children:"Previous: Integration Binding"}),p(b,{href:"/docs/safety/auditing",className:"btn-primary",children:["Audit Logs ",o(B,{size:16})]})]})]})}import{CodeBlock as g}from"@contractspec/lib.design-system";import k from"@contractspec/lib.ui-link";import{ChevronRight as q}from"lucide-react";import{jsx as t,jsxs as s}from"react/jsx-runtime";function L(){return s("div",{className:"space-y-8",children:[s("div",{className:"space-y-4",children:[t("h1",{className:"font-bold text-4xl",children:"Integration Binding"}),t("p",{className:"text-muted-foreground",children:"Integration binding connects your app's capabilities to external service providers. Each tenant can configure their own integration connections while sharing the same app blueprint."})]}),s("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"How it works"}),t("p",{className:"text-muted-foreground",children:"Integration binding follows a three-layer model:"}),s("ol",{className:"list-inside list-decimal space-y-3 text-muted-foreground",children:[s("li",{children:[t("strong",{children:"IntegrationSpec"})," (global) - Defines what an integration provides"]}),s("li",{children:[t("strong",{children:"IntegrationConnection"})," (per-tenant) - A tenant's configured connection"]}),s("li",{children:[t("strong",{children:"AppIntegrationBinding"})," (per-app) - Maps named slots to concrete tenant connections"]})]})]}),s("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Example: Payment processing"}),t("p",{className:"text-muted-foreground",children:"Let's walk through a complete example of binding Stripe for payments."}),s("div",{className:"space-y-3",children:[t("h3",{className:"font-semibold text-lg",children:"Step 1: Blueprint declares requirement"}),t(g,{language:"typescript",code:`// AppBlueprintSpec
{
  meta: { name: "invoice-app", version: '1.0.0', appId: "invoice" },
  integrationSlots: [
    {
      slotId: "payments.primary",
      requiredCategory: "payments",
      allowedModes: ["managed", "byok"],
      requiredCapabilities: [
        { key: "payments.createPaymentIntent", version: '1.0.0' },
        { key: "payments.createRefund", version: '1.0.0' }
      ],
      required: true,
      description: "Primary PSP used for Checkout and Subscription flows"
    }
  ],
  workflows: {
    checkout: { name: "invoice.checkout", version: '1.0.0' }
  },
  branding: {
    appNameKey: "invoice.appName",
    assets: [{ type: "logo", url: "https://cdn.acme.dev/logo.png" }],
    colorTokens: { primary: "colors.brand.primary" }
  }
}`})]}),s("div",{className:"space-y-3",children:[t("h3",{className:"font-semibold text-lg",children:"Step 2: Tenant creates connection"}),t(g,{language:"typescript",code:`// IntegrationConnection
{
  meta: {
    id: "conn_stripe_acme_prod",
    tenantId: "acme-corp",
    integrationKey: "payments.stripe",
    integrationVersion: 1,
    label: "Stripe Production",
    environment: "production",
    createdAt: "2025-01-15T09:00:00Z",
    updatedAt: "2025-01-15T10:30:00Z"
  },
  ownershipMode: "byok",
  externalAccountId: "acct_123",
  config: {
    accountId: "acct_123",
    webhookUrl: "https://acme.app/webhooks/stripe"
  },
  secretRef: "vault://integrations/acme/conn_stripe_acme_prod",
  status: "active"
}`})]}),s("div",{className:"space-y-3",children:[t("h3",{className:"font-semibold text-lg",children:"Step 3: TenantAppConfig binds connection"}),t(g,{language:"typescript",code:`// TenantAppConfig
{
  meta: {
    tenantId: "acme-corp",
    blueprintName: "invoice-app",
    blueprintVersion: 1,
    environment: "production",
    version: 4,
    status: "published"
  },
  integrations: [
    {
      slotId: "payments.primary",
      connectionId: "conn_stripe_acme_prod",
      scope: {
        workflows: ["checkout", "subscription-renewal", "refund-process"],
        operations: ["payments.stripe.*"]
      },
      priority: 1
    }
  ],
  branding: {
    appName: { en: "Acme Billing Portal" },
    customDomain: "billing.acme.com",
    assets: [{ type: "logo", url: "https://assets.acme.com/logo.svg" }]
  }
}`})]}),s("div",{className:"space-y-3",children:[t("h3",{className:"font-semibold text-lg",children:"Step 4: Runtime resolves and executes"}),t(g,{language:"typescript",code:`// ResolvedAppConfig (runtime)
{
  integrations: {
    "payments.createPaymentIntent": {
      provider: { /* IntegrationSpec for Stripe */ },
      connection: { /* IntegrationConnection */ },
      config: { /* Merged configuration */ }
    }
  }
}

// When workflow executes:
const result = await executeCapability(
  "payments.createPaymentIntent",
  { amount: 5000, currency: "usd" },
  resolvedConfig
);
// \u2192 Uses Stripe connection automatically`})]})]}),s("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Multi-integration scenarios"}),t("p",{className:"text-muted-foreground",children:"A single app can use multiple integrations across different categories:"}),t(g,{language:"typescript",code:`integrations: [
  {
    slotId: "payments.primary",
    connectionId: "conn_stripe_prod",
    scope: {
      workflows: ["checkout", "subscription-*"]
    }
  },
  {
    slotId: "email.outbound",
    connectionId: "conn_postmark_prod"
  },
  {
    slotId: "email.inbound",
    connectionId: "conn_gmail_support",
    scope: {
      workflows: ["support-ticket-creation"]
    }
  },
  {
    slotId: "knowledge.vector-store",
    connectionId: "conn_qdrant_prod",
    scope: {
      workflows: ["semantic-search", "rag-query"]
    }
  }
]`})]}),s("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Sandbox vs Production"}),t("p",{className:"text-muted-foreground",children:"Tenants typically maintain separate connections for sandbox and production environments:"}),t(g,{language:"typescript",code:`// Sandbox environment
{
  meta: { environment: "sandbox", status: "preview" },
  integrations: [
    {
      slotId: "payments.primary",
      connectionId: "conn_stripe_acme_test"
    }
  ]
}

// Production environment
{
  meta: { environment: "production", status: "published" },
  integrations: [
    {
      slotId: "payments.primary",
      connectionId: "conn_stripe_acme_prod"
    }
  ]
}`})]}),s("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Security & validation"}),s("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[t("li",{children:"Integration connections are validated before binding - health checks ensure connectivity"}),t("li",{children:"Secrets are never stored in TenantAppConfig - only references to encrypted secrets"}),t("li",{children:"Policy Decision Point (PDP) enforces which workflows can use which integrations"}),t("li",{children:"All integration calls are audited with full request/response logging"}),t("li",{children:"Rate limiting and quotas are enforced per connection"})]})]}),s("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Best practices"}),s("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[s("li",{children:["Use wildcard patterns sparingly in ",t("code",{children:"allowedWorkflows"})," - be explicit about access"]}),t("li",{children:"Always maintain separate sandbox and production connections"}),t("li",{children:"Monitor integration health checks and set up alerts for failures"}),t("li",{children:"Document the purpose of each integration binding for your team"}),t("li",{children:"Test integration changes in sandbox before promoting to production"})]})]}),s("div",{className:"flex items-center gap-4 pt-4",children:[t(k,{href:"/docs/architecture/app-config",className:"btn-ghost",children:"Previous: App Configuration"}),s(k,{href:"/docs/architecture/knowledge-binding",className:"btn-primary",children:["Knowledge Binding ",t(q,{size:16})]})]})]})}import{CodeBlock as y}from"@contractspec/lib.design-system";import C from"@contractspec/lib.ui-link";import{ChevronRight as K}from"lucide-react";import{jsx as e,jsxs as a}from"react/jsx-runtime";function D(){return a("div",{className:"space-y-8",children:[a("div",{className:"space-y-4",children:[e("h1",{className:"font-bold text-4xl",children:"Knowledge Binding"}),e("p",{className:"text-muted-foreground",children:"Knowledge binding connects your app's workflows and agents to structured knowledge spaces. This enables semantic search, RAG (Retrieval-Augmented Generation), and context-aware decision-making."})]}),a("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"How it works"}),e("p",{className:"text-muted-foreground",children:"Knowledge binding follows a three-layer model:"}),a("ol",{className:"list-inside list-decimal space-y-3 text-muted-foreground",children:[a("li",{children:[e("strong",{children:"KnowledgeSpaceSpec"})," (global) - Defines a logical knowledge domain"]}),a("li",{children:[e("strong",{children:"KnowledgeSourceConfig"})," (per-tenant) - Tenant's data sources feeding spaces"]}),a("li",{children:[e("strong",{children:"AppKnowledgeBinding"})," (per-app) - Maps spaces to workflows/agents"]})]})]}),a("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Example: Support agent with RAG"}),e("p",{className:"text-muted-foreground",children:"Let's build a support agent that uses canonical product documentation and operational support history."}),a("div",{className:"space-y-3",children:[e("h3",{className:"font-semibold text-lg",children:"Step 1: Blueprint declares knowledge needs"}),e(y,{language:"typescript",code:`// AppBlueprintSpec
{
  id: "support-app",
  version: "1.0.0",
  knowledgeSpaces: [
    {
      spaceId: "product-canon",
      category: "canonical",
      required: true,
      purpose: "Official product documentation and specs"
    },
    {
      spaceId: "support-history",
      category: "operational",
      required: true,
      purpose: "Past support tickets and resolutions"
    },
    {
      spaceId: "external-docs",
      category: "external",
      required: false,
      purpose: "Third-party integration documentation"
    }
  ]
}`})]}),a("div",{className:"space-y-3",children:[e("h3",{className:"font-semibold text-lg",children:"Step 2: Tenant configures sources"}),e(y,{language:"typescript",code:`// KnowledgeSourceConfig (per-tenant)
[
  {
    id: "src_notion_product_docs",
    tenantId: "acme-corp",
    spaceId: "product-canon",
    kind: "notion",
    location: "https://notion.so/acme/product-docs",
    syncPolicy: { interval: "1h" },
    lastSyncedAt: "2025-01-15T10:00:00Z"
  },
  {
    id: "src_gmail_support_threads",
    tenantId: "acme-corp",
    spaceId: "support-history",
    kind: "gmail",
    location: "support@acme.com",
    syncPolicy: { webhook: true },
    lastSyncedAt: "2025-01-15T10:30:00Z"
  },
  {
    id: "src_stripe_docs",
    tenantId: "acme-corp",
    spaceId: "external-docs",
    kind: "url",
    location: "https://stripe.com/docs",
    syncPolicy: { interval: "24h" },
    lastSyncedAt: "2025-01-15T00:00:00Z"
  }
]`})]}),a("div",{className:"space-y-3",children:[e("h3",{className:"font-semibold text-lg",children:"Step 3: TenantAppConfig binds spaces"}),e(y,{language:"typescript",code:`// TenantAppConfig
{
  tenantId: "acme-corp",
  blueprintId: "support-app",
  blueprintVersion: "1.0.0",
  knowledgeBindings: [
    {
      spaceId: "product-canon",
      enabled: true,
      allowedConsumers: {
        workflowIds: ["answer-question", "generate-docs"],
        agentIds: ["support-agent", "docs-agent"]
      },
      allowedCategories: ["canonical"],
      sources: ["src_notion_product_docs"]
    },
    {
      spaceId: "support-history",
      enabled: true,
      allowedConsumers: {
        workflowIds: ["answer-question", "escalate-ticket"],
        agentIds: ["support-agent"]
      },
      allowedCategories: ["operational"],
      sources: ["src_gmail_support_threads"]
    },
    {
      spaceId: "external-docs",
      enabled: true,
      allowedConsumers: {
        agentIds: ["support-agent"]
      },
      allowedCategories: ["external"],
      sources: ["src_stripe_docs"]
    }
  ]
}`})]}),a("div",{className:"space-y-3",children:[e("h3",{className:"font-semibold text-lg",children:"Step 4: Workflow uses knowledge"}),e(y,{language:"yaml",code:`// WorkflowSpec
workflowId: answer-question
version: '1.0.0'.0.0

steps:
  - id: generate-embedding
    capability: openai-embeddings
    inputs:
      text: \${input.question}
  
  - id: search-canonical
    capability: vector.search
    inputs:
      collection: "product-canon"
      vector: \${steps.generate-embedding.output.embedding}
      limit: 5
  
  - id: search-support-history
    capability: vector.search
    inputs:
      collection: "support-history"
      vector: \${steps.generate-embedding.output.embedding}
      limit: 3
  
  - id: generate-answer
    capability: openai-chat
    inputs:
      messages:
        - role: "system"
          content: |
            You are a support agent. Answer based on:
            1. Canonical docs (authoritative)
            2. Support history (helpful context)
            Only use external docs for integration questions.
        - role: "user"
          content: |
            Question: \${input.question}
            
            Canonical docs:
            \${steps.search-canonical.output.results}
            
            Support history:
            \${steps.search-support-history.output.results}`})]})]}),a("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Category-based access control"}),e("p",{className:"text-muted-foreground",children:"Different knowledge categories have different trust levels and access patterns:"}),e("div",{className:"overflow-x-auto rounded-lg border border-border/50",children:a("table",{className:"w-full text-left text-sm",children:[e("thead",{className:"bg-card/50",children:a("tr",{className:"border-border/50 border-b",children:[e("th",{className:"px-4 py-3 font-semibold",children:"Category"}),e("th",{className:"px-4 py-3 font-semibold",children:"Trust Level"}),e("th",{className:"px-4 py-3 font-semibold",children:"Use Cases"}),e("th",{className:"px-4 py-3 font-semibold",children:"Policy Impact"})]})}),a("tbody",{className:"divide-y divide-border/50",children:[a("tr",{children:[e("td",{className:"px-4 py-3 font-mono text-xs",children:"canonical"}),e("td",{className:"px-4 py-3",children:"Highest"}),e("td",{className:"px-4 py-3",children:"Product specs, schemas, official policies"}),e("td",{className:"px-4 py-3",children:"Can drive policy decisions"})]}),a("tr",{children:[e("td",{className:"px-4 py-3 font-mono text-xs",children:"operational"}),e("td",{className:"px-4 py-3",children:"High"}),e("td",{className:"px-4 py-3",children:"Support tickets, sales docs, internal runbooks"}),e("td",{className:"px-4 py-3",children:"Can inform decisions"})]}),a("tr",{children:[e("td",{className:"px-4 py-3 font-mono text-xs",children:"external"}),e("td",{className:"px-4 py-3",children:"Medium"}),e("td",{className:"px-4 py-3",children:"Third-party docs, regulations, PSP guides"}),e("td",{className:"px-4 py-3",children:"Reference only, not authoritative"})]}),a("tr",{children:[e("td",{className:"px-4 py-3 font-mono text-xs",children:"ephemeral"}),e("td",{className:"px-4 py-3",children:"Low"}),e("td",{className:"px-4 py-3",children:"Agent scratchpads, session context, drafts"}),e("td",{className:"px-4 py-3",children:"Never used for decisions"})]})]})]})})]}),a("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Multi-space workflows"}),e("p",{className:"text-muted-foreground",children:"Workflows can query multiple knowledge spaces and combine results:"}),e(y,{language:"typescript",code:`knowledgeBindings: [
  {
    spaceId: "product-canon",
    enabled: true,
    allowedConsumers: {
      workflowIds: ["invoice-generation", "quote-creation"]
    },
    allowedCategories: ["canonical"],
    sources: ["src_database_schema", "src_product_catalog"]
  },
  {
    spaceId: "pricing-rules",
    enabled: true,
    allowedConsumers: {
      workflowIds: ["invoice-generation", "quote-creation"]
    },
    allowedCategories: ["canonical", "operational"],
    sources: ["src_pricing_database", "src_discount_policies"]
  },
  {
    spaceId: "customer-history",
    enabled: true,
    allowedConsumers: {
      workflowIds: ["quote-creation"]
    },
    allowedCategories: ["operational"],
    sources: ["src_crm_data", "src_past_invoices"]
  }
]`})]}),a("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Security & validation"}),a("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[e("li",{children:"Knowledge sources are validated before sync - credentials and permissions checked"}),e("li",{children:"PDP enforces which workflows/agents can access which spaces"}),e("li",{children:"All knowledge queries are audited with search terms and results"}),e("li",{children:"Canonical knowledge is immutable once indexed - changes require re-sync"}),e("li",{children:"Ephemeral knowledge is automatically purged based on retention policies"})]})]}),a("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Best practices"}),a("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[e("li",{children:"Use canonical spaces for policy-critical decisions, operational for suggestions"}),e("li",{children:"Never allow workflows to write to canonical spaces - maintain read-only access"}),e("li",{children:"Set up monitoring for sync failures and stale knowledge sources"}),e("li",{children:"Document the purpose and trust level of each knowledge space"}),e("li",{children:"Test knowledge queries in sandbox before promoting to production"}),a("li",{children:["Use explicit ",e("code",{children:"allowedConsumers"})," - avoid wildcard access"]})]})]}),a("div",{className:"flex items-center gap-4 pt-4",children:[e(C,{href:"/docs/architecture/integration-binding",className:"btn-ghost",children:"Previous: Integration Binding"}),a(C,{href:"/docs/knowledge",className:"btn-primary",children:["Knowledge & Context ",e(K,{size:16})]})]})]})}import{CodeBlock as E}from"@contractspec/lib.design-system";import I from"@contractspec/lib.ui-link";import{ChevronRight as M}from"lucide-react";import{jsx as c,jsxs as l}from"react/jsx-runtime";function U(){return l("div",{className:"space-y-8",children:[l("div",{className:"space-y-4",children:[c("h1",{className:"font-bold text-4xl",children:"Multi-Tenancy"}),c("p",{className:"text-muted-foreground",children:"ContractSpec is designed from the ground up for multi-tenancy. Apps built with ContractSpec can serve multiple organizations (tenants) from a single deployment, while ensuring strict data isolation and configuration separation."})]}),l("div",{className:"space-y-4",children:[c("h2",{className:"font-bold text-2xl",children:"Core Concepts"}),l("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[l("li",{children:[c("strong",{children:"Tenant"}),": An organization or customer that uses your app. Each tenant has a unique ",c("code",{children:"tenantId"}),"."]}),l("li",{children:[c("strong",{children:"Tenant Isolation"}),": Data and configuration for one tenant is never accessible to another tenant unless explicitly shared."]}),l("li",{children:[c("strong",{children:"Tenant Context"}),": Every request and operation runs within the context of a specific tenant."]})]})]}),l("div",{className:"space-y-4",children:[c("h2",{className:"font-bold text-2xl",children:"Tenant Resolution"}),c("p",{className:"text-muted-foreground",children:"The runtime automatically resolves the tenant context for every request based on:"}),l("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[l("li",{children:["Subdomain (e.g., ",c("code",{children:"acme.app.com"}),")"]}),l("li",{children:["Custom Domain (e.g., ",c("code",{children:"portal.acme.com"}),")"]}),l("li",{children:["Header (e.g., ",c("code",{children:"x-tenant-id: acme-corp"}),")"]}),c("li",{children:"Authentication Token (embedded tenant claim)"})]})]}),l("div",{className:"space-y-4",children:[c("h2",{className:"font-bold text-2xl",children:"Configuration Isolation"}),l("p",{className:"text-muted-foreground",children:["Each tenant has its own ",c("code",{children:"TenantAppConfig"})," which defines:"]}),c(E,{language:"typescript",code:`type TenantAppConfig = {
  tenantId: string;
  blueprintId: string;
  // ...
  integrationBindings: AppIntegrationBinding[];
  knowledgeBindings: AppKnowledgeBinding[];
  featureFlags: Record<string, boolean>;
};`}),c("p",{className:"mt-2 text-muted-foreground",children:"This allows you to customize feature flags, integration connections, and knowledge sources per tenant without changing the application code."})]}),l("div",{className:"flex items-center gap-4 pt-4",children:[c(I,{href:"/docs/architecture",className:"btn-ghost",children:"Back to Architecture"}),l(I,{href:"/docs/libraries/multi-tenancy",className:"btn-primary",children:["Multi-Tenancy Library ",c(M,{size:16})]})]})]})}import f from"@contractspec/lib.ui-link";import{jsx as i,jsxs as d}from"react/jsx-runtime";var z=[{title:"Contracts and schemas",body:"Explicit specs define the durable boundary for behavior, data, and governance."},{title:"Bindings and configuration",body:"Apps, tenants, integrations, and knowledge sources are wired through explicit configuration instead of hidden glue."},{title:"Runtimes and generators",body:"Serve or generate aligned surfaces for API, UI, workflows, docs, and agent-facing interfaces."},{title:"Operate and observe",body:"Carry auditability, policy, tracing, migrations, and tenant isolation through the same model."}];function H(){return d("div",{className:"space-y-10",children:[d("div",{className:"space-y-3",children:[i("p",{className:"editorial-kicker",children:"Build"}),i("h1",{className:"font-serif text-4xl tracking-[-0.04em] md:text-5xl",children:"The architecture keeps contracts, runtime behavior, and operations in the same system."}),i("p",{className:"max-w-3xl text-lg text-muted-foreground leading-8",children:"ContractSpec is not a single runtime. It is a layered system that lets you define explicit boundaries, bind real-world configuration, and then serve or generate aligned surfaces without losing control of the output."})]}),i("div",{className:"grid gap-4 md:grid-cols-2",children:z.map((m)=>d("article",{className:"editorial-panel space-y-3",children:[i("h2",{className:"font-semibold text-xl",children:m.title}),i("p",{className:"text-muted-foreground text-sm leading-7",children:m.body})]},m.title))}),d("section",{className:"editorial-panel space-y-5",children:[d("div",{className:"space-y-2",children:[i("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"UI composition belongs in the bundle runtime layer"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"When the system needs adaptive layouts, entity workbenches, assistant slots, and safe overlays, use module bundles as the layer between the contract model and the rendered surface."})]}),d("div",{className:"grid gap-4 md:grid-cols-2",children:[d(f,{href:"/docs/specs/module-bundles",className:"docs-footer-link",children:[i("h3",{className:"font-semibold text-lg",children:"Module bundles spec"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"See the typed bundle contract, resolved surface plan model, and bounded AI/runtime behavior."})]}),d(f,{href:"/docs/guides/first-module-bundle",className:"docs-footer-link",children:[i("h3",{className:"font-semibold text-lg",children:"Build a first module bundle"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"Follow the route-to-plan-to-render path with one practical host example."})]})]})]}),d("section",{className:"editorial-panel space-y-5",children:[d("div",{className:"space-y-2",children:[i("h2",{className:"font-serif text-3xl tracking-[-0.03em]",children:"Follow the architecture by responsibility"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"Use the architecture pages when you need to understand how the pieces snap together in a real deployment."})]}),d("div",{className:"grid gap-4 md:grid-cols-2",children:[d(f,{href:"/docs/architecture/app-config",className:"docs-footer-link",children:[i("h3",{className:"font-semibold text-lg",children:"App configuration"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"How blueprint-level and tenant-level config stay explicit and merge safely."})]}),d(f,{href:"/docs/architecture/integration-binding",className:"docs-footer-link",children:[i("h3",{className:"font-semibold text-lg",children:"Integration binding"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"How apps connect to tenant-owned integrations without leaking provider logic everywhere."})]}),d(f,{href:"/docs/architecture/knowledge-binding",className:"docs-footer-link",children:[i("h3",{className:"font-semibold text-lg",children:"Knowledge binding"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"How trusted knowledge enters the system and stays isolated by context and tenant."})]}),d(f,{href:"/docs/architecture/control-plane",className:"docs-footer-link",children:[i("h3",{className:"font-semibold text-lg",children:"Control plane runtime"}),i("p",{className:"text-muted-foreground text-sm leading-7",children:"How intent, policy, planning, and execution flow through the system runtime."})]})]})]})]})}export{H as ArchitectureOverviewPage,U as ArchitectureMultiTenancyPage,D as ArchitectureKnowledgeBindingPage,L as ArchitectureIntegrationBindingPage,R as ArchitectureControlPlanePage,T as ArchitectureAppConfigPage};
