// @bun
import g from"@contractspec/lib.ui-link";import{ChevronRight as S}from"lucide-react";import{jsx as t,jsxs as i}from"react/jsx-runtime";function P(){return i("div",{className:"space-y-8",children:[i("div",{className:"space-y-4",children:[t("h1",{className:"font-bold text-4xl",children:"Audit Logs"}),i("p",{className:"text-muted-foreground",children:["An ",t("strong",{children:"audit log"})," (also called an audit trail) is a chronological record of system activities. According to"," ",t("a",{href:"https://www.sumologic.com/glossary/audit-log/",target:"_blank",rel:"noopener noreferrer",className:"text-violet-400 hover:text-violet-300",children:"Sumo Logic"}),', audit logs "provide a detailed record of events and changes within a system, enabling organizations to track user actions, system changes, and access to sensitive data."']})]}),i("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Why audit logs matter"}),i("div",{className:"space-y-3",children:[i("div",{children:[t("h3",{className:"font-semibold text-lg",children:"Accountability"}),t("p",{className:"text-muted-foreground",children:'Audit logs answer the question "who did what, when?" This is essential for holding users and administrators accountable for their actions. If data is deleted or modified, the audit log shows exactly who made the change.'})]}),i("div",{children:[t("h3",{className:"font-semibold text-lg",children:"Security"}),t("p",{className:"text-muted-foreground",children:"Audit logs help detect and investigate security incidents. For example, if an attacker gains unauthorized access, the logs reveal which resources they accessed and what actions they performed. This information is critical for incident response and forensics."})]}),i("div",{children:[t("h3",{className:"font-semibold text-lg",children:"Compliance"}),t("p",{className:"text-muted-foreground",children:"Many regulations (GDPR, HIPAA, SOC 2, PCI DSS) require organizations to maintain audit logs. These logs must be tamper-evident, retained for a specified period, and available for inspection by auditors."})]}),i("div",{children:[t("h3",{className:"font-semibold text-lg",children:"Debugging"}),t("p",{className:"text-muted-foreground",children:"When something goes wrong in production, audit logs provide a detailed timeline of events leading up to the failure. This makes it much easier to diagnose and fix issues."})]})]})]}),i("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"What ContractSpec logs"}),t("p",{className:"text-muted-foreground",children:"ContractSpec automatically logs every significant operation, including:"}),i("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[i("li",{children:[t("strong",{children:"API calls"})," \u2013 Every invocation of a capability, including inputs, outputs, and the user who made the call."]}),i("li",{children:[t("strong",{children:"Policy decisions"})," \u2013 Every decision made by the"," ",t(g,{href:"/docs/safety/pdp",className:"text-violet-400 hover:text-violet-300",children:"Policy Decision Point"}),", including the rule that matched and the reason for the decision."]}),i("li",{children:[t("strong",{children:"Data access"})," \u2013 Every query to a data view, including which fields were accessed and whether any were redacted."]}),i("li",{children:[t("strong",{children:"Workflow execution"})," \u2013 Every step in a workflow, including retries, compensations, and failures."]}),i("li",{children:[t("strong",{children:"Administrative actions"})," \u2013 Spec deployments, configuration changes, user role assignments, and other privileged operations."]}),i("li",{children:[t("strong",{children:"Authentication events"})," \u2013 Login attempts, password resets, and session expirations."]})]})]}),i("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Audit log format"}),t("p",{className:"text-muted-foreground",children:"Each audit log entry is a structured JSON object containing:"}),t("div",{className:"overflow-x-auto rounded-lg border border-border bg-background/50 p-4 font-mono text-muted-foreground text-sm",children:t("pre",{children:`{
  "timestamp": "2025-11-13T14:32:15.123Z",
  "eventId": "evt_abc123",
  "eventType": "capability.invoked",
  "actor": {
    "userId": "user_xyz789",
    "role": "admin",
    "ipAddress": "203.0.113.42"
  },
  "resource": {
    "type": "capability",
    "id": "transferFunds",
    "version": "1.2.0"
  },
  "action": "execute",
  "result": "success",
  "metadata": {
    "inputs": {
      "recipient": "user_def456",
      "amount": 100.00
    },
    "outputs": {
      "transactionId": "txn_ghi789",
      "timestamp": "2025-11-13T14:32:15.456Z"
    }
  },
  "policyDecision": {
    "decision": "PERMIT",
    "ruleId": "allow-admin-transfers",
    "reason": "User has admin role"
  }
}`})})]}),i("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Storage and retention"}),t("p",{className:"text-muted-foreground",children:"Audit logs are stored in a tamper-evident append-only log. Once written, entries cannot be modified or deleted. This ensures the integrity of the audit trail."}),t("p",{className:"text-muted-foreground",children:"ContractSpec supports multiple storage backends:"}),i("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[i("li",{children:[t("strong",{children:"Local file system"})," \u2013 For development and testing."]}),i("li",{children:[t("strong",{children:"Cloud object storage"})," \u2013 S3, GCS, or Azure Blob Storage for production."]}),i("li",{children:[t("strong",{children:"SIEM integration"})," \u2013 Forward logs to Splunk, Datadog, or other security information and event management systems."]})]}),t("p",{className:"text-muted-foreground",children:"You can configure retention policies to automatically archive or delete old logs after a specified period (e.g., 7 years for GDPR compliance)."})]}),i("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Querying audit logs"}),t("p",{className:"text-muted-foreground",children:"ContractSpec provides a query API for searching audit logs. You can filter by:"}),i("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[t("li",{children:"Time range"}),t("li",{children:"Event type"}),t("li",{children:"Actor (user ID, role, IP address)"}),t("li",{children:"Resource (capability, data view, workflow)"}),t("li",{children:"Result (success, failure, denied)"})]}),t("p",{className:"text-muted-foreground",children:'Example query: "Show all failed login attempts from IP address 203.0.113.42 in the last 24 hours."'})]}),i("div",{className:"space-y-4",children:[t("h2",{className:"font-bold text-2xl",children:"Best practices"}),i("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[i("li",{children:[t("strong",{children:"Review logs regularly"})," \u2013 Set up alerts for suspicious activity (e.g., repeated failed login attempts, unauthorized access attempts)."]}),i("li",{children:[t("strong",{children:"Protect log access"})," \u2013 Only authorized personnel should be able to view audit logs. Use role-based access control to restrict access."]}),i("li",{children:[t("strong",{children:"Retain logs long enough"})," \u2013 Check your compliance requirements and configure retention policies accordingly."]}),i("li",{children:[t("strong",{children:"Test log integrity"})," \u2013 Periodically verify that logs have not been tampered with by checking cryptographic signatures."]})]})]}),i("div",{className:"flex items-center gap-4 pt-4",children:[t(g,{href:"/docs/safety/pdp",className:"btn-ghost",children:"Previous: Policy Decision Points"}),i(g,{href:"/docs/safety/migrations",className:"btn-primary",children:["Next: Migrations ",t(S,{size:16})]})]})]})}import b from"@contractspec/lib.ui-link";import{ChevronRight as w}from"lucide-react";import{jsx as e,jsxs as o}from"react/jsx-runtime";function T(){return o("div",{className:"space-y-8",children:[o("div",{className:"space-y-4",children:[e("h1",{className:"font-bold text-4xl",children:"Migrations"}),o("p",{className:"text-muted-foreground",children:["A ",e("strong",{children:"schema migration"})," (also called a database migration) is a set of incremental, reversible changes to a database schema. According to"," ",e("a",{href:"https://en.wikipedia.org/wiki/Schema_migration",target:"_blank",rel:"noopener noreferrer",className:"text-violet-400 hover:text-violet-300",children:"Wikipedia"}),`, schema migrations "allow the database schema to evolve as the application's requirements change, while preserving existing data."`]})]}),o("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Why migrations matter"}),e("p",{className:"text-muted-foreground",children:"As your application evolves, you'll need to change your data model\u2014adding new fields, renaming tables, changing data types, or restructuring relationships. Without a disciplined approach, these changes can lead to:"}),o("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[e("li",{children:"Data loss or corruption"}),e("li",{children:"Downtime during deployments"}),e("li",{children:"Inconsistencies between environments (dev, staging, production)"}),e("li",{children:"Difficulty rolling back failed changes"})]}),e("p",{className:"text-muted-foreground",children:"Migrations solve these problems by treating schema changes as versioned, tested, and reversible operations."})]}),o("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"How MigrationSpec works"}),o("p",{className:"text-muted-foreground",children:["In ContractSpec, migrations are defined using"," ",e("strong",{children:"MigrationSpec"}),". Each migration has:"]}),o("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[o("li",{children:[e("strong",{children:"Version"}),' \u2013 A unique identifier (e.g., "2025-11-13-001") that determines the order of execution.']}),o("li",{children:[e("strong",{children:"Up function"}),` \u2013 The forward migration that applies the change (e.g., "add column 'email_verified'").`]}),o("li",{children:[e("strong",{children:"Down function"}),` \u2013 The reverse migration that undoes the change (e.g., "drop column 'email_verified'").`]}),o("li",{children:[e("strong",{children:"Dependencies"})," \u2013 Other migrations that must run before this one."]}),o("li",{children:[e("strong",{children:"Validation"}),' \u2013 Optional checks to ensure the migration succeeded (e.g., "verify all users have an email address").']})]})]}),o("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Example MigrationSpec"}),e("p",{className:"text-muted-foreground",children:"Here's a migration that adds an email verification field to the users table:"}),e("div",{className:"overflow-x-auto rounded-lg border border-border bg-background/50 p-4 font-mono text-muted-foreground text-sm",children:e("pre",{children:`migrationId: add-email-verified
version: 2025-11-13-001
dependencies: []

up:
  - sql: |
      ALTER TABLE users
      ADD COLUMN email_verified BOOLEAN DEFAULT FALSE NOT NULL;
  - sql: |
      CREATE INDEX idx_users_email_verified
      ON users(email_verified);

down:
  - sql: |
      DROP INDEX idx_users_email_verified;
  - sql: |
      ALTER TABLE users
      DROP COLUMN email_verified;

validation:
  - sql: |
      SELECT COUNT(*) FROM users
      WHERE email_verified IS NULL;
    expectZeroRows: true`})})]}),o("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Running migrations"}),e("p",{className:"text-muted-foreground",children:"Migrations are applied automatically during deployment. The ContractSpec runtime:"}),o("ol",{className:"list-inside list-decimal space-y-2 text-muted-foreground",children:[e("li",{children:"Checks which migrations have already been applied (stored in a migrations table)."}),e("li",{children:"Identifies new migrations that need to run."}),e("li",{children:"Executes them in order, respecting dependencies."}),e("li",{children:"Runs validation checks to ensure success."}),e("li",{children:"Records the migration as applied."})]}),e("p",{className:"text-muted-foreground",children:"If a migration fails, the deployment is aborted, and the system remains in its previous state. You can then fix the migration and redeploy."})]}),o("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Rolling back migrations"}),o("p",{className:"text-muted-foreground",children:["If you need to roll back a deployment, ContractSpec automatically runs the ",e("strong",{children:"down"})," functions of any migrations that were applied. This restores the database to its previous state."]}),e("p",{className:"text-muted-foreground",children:"Note that rollbacks are not always possible\u2014for example, if you've deleted a column, you cannot recover the data unless you have a backup. For destructive changes, it's best to use a multi-step migration:"}),o("ol",{className:"list-inside list-decimal space-y-2 text-muted-foreground",children:[e("li",{children:"Add the new column (reversible)."}),e("li",{children:"Backfill data from the old column to the new column (reversible)."}),e("li",{children:"Update application code to use the new column (reversible)."}),e("li",{children:"Drop the old column (irreversible\u2014only do this after confirming the new column works)."})]})]}),o("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Best practices"}),o("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[o("li",{children:[e("strong",{children:"Test migrations locally"})," \u2013 Run them against a copy of production data to catch issues before deploying."]}),o("li",{children:[e("strong",{children:"Keep migrations small"})," \u2013 Each migration should do one thing. This makes them easier to understand and roll back."]}),o("li",{children:[e("strong",{children:"Write reversible migrations"})," \u2013 Always provide a down function, even if you don't plan to roll back."]}),o("li",{children:[e("strong",{children:"Use transactions"})," \u2013 Wrap migrations in database transactions so they either fully succeed or fully fail."]}),o("li",{children:[e("strong",{children:"Avoid destructive changes"})," \u2013 Prefer additive changes (adding columns) over destructive ones (dropping columns). If you must delete data, archive it first."]}),o("li",{children:[e("strong",{children:"Version your migrations"})," \u2013 Use timestamps or sequential numbers to ensure migrations run in the correct order."]}),o("li",{children:[e("strong",{children:"Document breaking changes"})," \u2013 If a migration requires application code changes, note this in the migration description."]})]})]}),o("div",{className:"space-y-4",children:[e("h2",{className:"font-bold text-2xl",children:"Zero-downtime migrations"}),e("p",{className:"text-muted-foreground",children:"Some migrations can cause downtime if not handled carefully. For example, adding a NOT NULL column to a large table can lock the table for minutes. To avoid this, use a multi-step approach:"}),o("ol",{className:"list-inside list-decimal space-y-2 text-muted-foreground",children:[e("li",{children:"Add the column as nullable."}),e("li",{children:"Backfill the column in batches (without locking the table)."}),e("li",{children:"Add the NOT NULL constraint once all rows are populated."})]}),e("p",{className:"text-muted-foreground",children:"ContractSpec's migration system supports this pattern by allowing you to split a logical change into multiple versioned migrations."})]}),o("div",{className:"flex items-center gap-4 pt-4",children:[e(b,{href:"/docs/safety/auditing",className:"btn-ghost",children:"Previous: Audit Logs"}),o(b,{href:"/docs/advanced/renderers",className:"btn-primary",children:["Next: Advanced Topics ",e(w,{size:16})]})]})]})}import I from"@contractspec/lib.ui-link";import{jsx as c,jsxs as u}from"react/jsx-runtime";var k=[{title:"Spec signing",body:"Protect the integrity of what gets deployed and make changes verifiable.",href:"/docs/safety/signing"},{title:"Policy decision points",body:"Apply governance consistently across operations, data access, and generated surfaces.",href:"/docs/safety/pdp"},{title:"Audit trails",body:"Record operational and policy decisions with enough context to inspect and explain them later.",href:"/docs/safety/auditing"},{title:"Migrations",body:"Evolve data and schema boundaries without losing control of the system.",href:"/docs/safety/migrations"},{title:"Tenant isolation",body:"Keep configuration, access rules, and sensitive data bounded by tenant.",href:"/docs/safety/tenant-isolation"},{title:"Security and trust",body:"Understand the trust model, release process, and security expectations around the OSS system.",href:"/docs/safety/security-trust"}];function D(){return u("div",{className:"space-y-10",children:[u("div",{className:"space-y-3",children:[c("p",{className:"editorial-kicker",children:"Operate"}),c("h1",{className:"font-serif text-4xl tracking-[-0.04em] md:text-5xl",children:"Safety is part of the system model, not an afterthought."}),c("p",{className:"max-w-3xl text-lg text-muted-foreground leading-8",children:"ContractSpec is meant to survive real change: new generated surfaces, policy updates, migrations, integration churn, and operator handoffs. The safety layer makes those changes inspectable, reversible, and governed."})]}),u("div",{className:"editorial-proof-strip",children:[u("div",{className:"editorial-stat",children:[c("span",{className:"editorial-label",children:"Operating rule"}),c("span",{className:"editorial-stat-value",children:"explicit change beats hidden mutation"})]}),c("p",{className:"max-w-2xl text-muted-foreground text-sm leading-7",children:"Use policies, signing, audit trails, and migrations to keep the system legible even as AI-assisted workflows accelerate change volume."})]}),c("div",{className:"grid gap-4 md:grid-cols-2",children:k.map((y)=>u(I,{href:y.href,className:"editorial-panel",children:[c("h2",{className:"font-semibold text-xl",children:y.title}),c("p",{className:"mt-2 text-muted-foreground text-sm leading-7",children:y.body})]},y.href))})]})}import h from"@contractspec/lib.ui-link";import{ChevronRight as R}from"lucide-react";import{jsx as a,jsxs as l}from"react/jsx-runtime";function A(){return l("div",{className:"space-y-8",children:[l("div",{className:"space-y-4",children:[a("h1",{className:"font-bold text-4xl",children:"Policy Decision Points"}),l("p",{className:"text-muted-foreground",children:["A ",a("strong",{children:"Policy Decision Point (PDP)"})," is a centralized component that evaluates access control policies and makes authorization decisions. According to"," ",a("a",{href:"https://www.strongdm.com/blog/policy-decision-point",target:"_blank",rel:"noopener noreferrer",className:"text-violet-400 hover:text-violet-300",children:"StrongDM"}),', the PDP "receives requests for access to resources, evaluates them against policies, and returns a decision (permit or deny)."']})]}),l("div",{className:"space-y-4",children:[a("h2",{className:"font-bold text-2xl",children:"How the PDP works in ContractSpec"}),a("p",{className:"text-muted-foreground",children:"In ContractSpec, the PDP is invoked on every operation\u2014whether it's rendering a UI component, executing a capability, or querying a data view. The flow is:"}),l("ol",{className:"list-inside list-decimal space-y-3 text-muted-foreground",children:[l("li",{children:[a("strong",{children:"Request evaluation"})," \u2013 The runtime sends a request to the PDP containing:",l("ul",{className:"mt-2 ml-6 list-inside list-disc space-y-1",children:[a("li",{children:"The user's identity and attributes (roles, groups, location, etc.)"}),a("li",{children:"The resource being accessed (capability, field, workflow step)"}),a("li",{children:"The action being performed (read, write, execute)"}),a("li",{children:"Contextual information (time of day, device type, IP address)"})]})]}),l("li",{children:[a("strong",{children:"Policy evaluation"})," \u2013 The PDP evaluates the request against all applicable ",a("strong",{children:"PolicySpecs"}),". These specs define rules using attribute-based access control (ABAC) and can reference:",l("ul",{className:"mt-2 ml-6 list-inside list-disc space-y-1",children:[a("li",{children:`User attributes (e.g., "role == 'admin'")`}),a("li",{children:`Resource attributes (e.g., "field.sensitivity == 'PII'")`}),a("li",{children:'Environmental attributes (e.g., "time.hour >= 9 AND time.hour < 17")'})]})]}),l("li",{children:[a("strong",{children:"Decision return"})," \u2013 The PDP returns one of:",l("ul",{className:"mt-2 ml-6 list-inside list-disc space-y-1",children:[l("li",{children:[a("code",{className:"rounded bg-background/50 px-2 py-1",children:"PERMIT"})," ","\u2013 The operation is allowed."]}),l("li",{children:[a("code",{className:"rounded bg-background/50 px-2 py-1",children:"DENY"})," ","\u2013 The operation is blocked."]}),l("li",{children:[a("code",{className:"rounded bg-background/50 px-2 py-1",children:"REDACT"})," ","\u2013 The operation is allowed, but sensitive fields are masked."]})]})]}),l("li",{children:[a("strong",{children:"Enforcement"})," \u2013 The runtime enforces the decision. If denied, the operation fails with a clear error message. If redacted, sensitive fields are replaced with placeholders."]}),l("li",{children:[a("strong",{children:"Auditing"})," \u2013 Every PDP decision is logged to the"," ",a(h,{href:"/docs/safety/auditing",className:"text-violet-400 hover:text-violet-300",children:"audit log"}),", including the request, decision, and reasoning."]})]})]}),l("div",{className:"space-y-4",children:[a("h2",{className:"font-bold text-2xl",children:"Example PolicySpec"}),a("p",{className:"text-muted-foreground",children:"Here's a simple policy that restricts access to PII fields:"}),a("div",{className:"overflow-x-auto rounded-lg border border-border bg-background/50 p-4 font-mono text-muted-foreground text-sm",children:a("pre",{children:`policyId: pii-access-control
version: '1.0.0'.0.0
rules:
  - id: allow-admin-full-access
    effect: PERMIT
    condition: user.role == 'admin'
    
  - id: redact-pii-for-support
    effect: REDACT
    condition: |
      user.role == 'support' AND
      field.sensitivity == 'PII'
    redactFields: ['ssn', 'creditCard', 'dateOfBirth']
    
  - id: deny-pii-for-others
    effect: DENY
    condition: |
      user.role NOT IN ['admin', 'support'] AND
      field.sensitivity == 'PII'`})}),a("p",{className:"text-muted-foreground",children:"With this policy, admins see all data, support staff see redacted PII, and other users cannot access PII at all."})]}),l("div",{className:"space-y-4",children:[a("h2",{className:"font-bold text-2xl",children:"Benefits of centralized decision-making"}),l("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[l("li",{children:[a("strong",{children:"Consistency"})," \u2013 Policies are enforced uniformly across all surfaces (API, UI, workflows)."]}),l("li",{children:[a("strong",{children:"Auditability"})," \u2013 Every decision is logged, making it easy to trace why access was granted or denied."]}),l("li",{children:[a("strong",{children:"Flexibility"})," \u2013 Policies can be updated without changing application code."]}),l("li",{children:[a("strong",{children:"Security"})," \u2013 Reduces the risk of authorization bugs by removing ad-hoc checks scattered throughout the codebase."]})]})]}),l("div",{className:"space-y-4",children:[a("h2",{className:"font-bold text-2xl",children:"Performance considerations"}),a("p",{className:"text-muted-foreground",children:"Because the PDP is invoked on every operation, performance is critical. ContractSpec optimizes this by:"}),l("ul",{className:"list-inside list-disc space-y-2 text-muted-foreground",children:[a("li",{children:"Caching policy decisions for identical requests"}),a("li",{children:"Compiling policies into efficient bytecode"}),a("li",{children:"Evaluating only the minimal set of rules needed for each request"}),a("li",{children:"Running the PDP in-process to avoid network latency"})]}),a("p",{className:"text-muted-foreground",children:"In practice, PDP overhead is typically less than 1ms per request."})]}),l("div",{className:"flex items-center gap-4 pt-4",children:[a(h,{href:"/docs/safety/signing",className:"btn-ghost",children:"Previous: Spec Signing"}),l(h,{href:"/docs/safety/auditing",className:"btn-primary",children:["Next: Audit Logs ",a(R,{size:16})]})]})]})}import v from"@contractspec/lib.ui-link";import{ChevronRight as N}from"lucide-react";import{jsx as r,jsxs as d}from"react/jsx-runtime";function q(){return d("div",{className:"space-y-8",children:[d("div",{className:"space-y-4",children:[r("h1",{className:"font-bold text-4xl",children:"Security & Trust"}),r("p",{className:"text-muted-foreground",children:"ContractSpec focuses on deterministic, auditable software delivery. This page summarizes our security posture and trust commitments so teams can adopt with clarity."})]}),d("div",{className:"card-subtle space-y-4 p-6",children:[r("h2",{className:"font-bold text-2xl",children:"Security policy"}),r("p",{className:"text-muted-foreground text-sm",children:"We publish a dedicated security policy that explains how to report vulnerabilities and how we respond."}),d(v,{href:"/SECURITY.md",className:"btn-primary",children:["Read the security policy ",r(N,{size:16})]})]}),d("div",{className:"grid gap-4 md:grid-cols-2",children:[d("div",{className:"card-subtle space-y-3 p-6",children:[r("h3",{className:"font-semibold text-lg",children:"Release hygiene"}),r("p",{className:"text-muted-foreground text-sm",children:"We ship with deterministic CI, changesets, and contract validation so teams can trust every release."}),d("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[r("li",{children:"Changesets required for published packages."}),r("li",{children:"CI gate for contract validation and drift detection."}),r("li",{children:"Rollback-friendly release process."})]})]}),d("div",{className:"card-subtle space-y-3 p-6",children:[r("h3",{className:"font-semibold text-lg",children:"Data handling"}),r("p",{className:"text-muted-foreground text-sm",children:"ContractSpec promotes strict data classification and policy-driven access. Specs can tag sensitive fields for enforcement."}),d("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[r("li",{children:"Schema-level sensitivity tags."}),r("li",{children:"Policy Decision Point enforcement."}),r("li",{children:"Audit logs for operational traceability."})]})]})]}),d("div",{className:"grid gap-4 md:grid-cols-2",children:[d("div",{className:"card-subtle space-y-3 p-6",children:[r("h3",{className:"font-semibold text-lg",children:"Supply chain"}),r("p",{className:"text-muted-foreground text-sm",children:"We track dependency updates and keep the monorepo build reproducible."}),d("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[r("li",{children:"Dependabot + Renovate-style updates where available."}),r("li",{children:"Signed release artifacts planned for Studio release cycles."}),r("li",{children:"Transparent changelogs for every package."})]})]}),d("div",{className:"card-subtle space-y-3 p-6",children:[r("h3",{className:"font-semibold text-lg",children:"Responsible disclosure"}),r("p",{className:"text-muted-foreground text-sm",children:"We respond quickly to security reports and coordinate fixes before public disclosure."}),d("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[r("li",{children:"Security response within 5 business days."}),r("li",{children:"Private disclosure via security@contractspec.io."}),r("li",{children:"Credit for researchers (with permission)."})]})]})]}),d("div",{className:"space-y-4",children:[r("h2",{className:"font-bold text-2xl",children:"Next steps"}),r("p",{className:"text-muted-foreground",children:"Explore the broader safety controls or read the roadmap to see upcoming trust investments."}),d("div",{className:"flex flex-wrap gap-4 pt-4",children:[d(v,{href:"/docs/safety",className:"btn-ghost",children:["Safety overview ",r(N,{size:16})]}),d(v,{href:"/ROADMAP.md",className:"btn-ghost",children:["Roadmap ",r(N,{size:16})]})]})]})]})}import E from"@contractspec/lib.ui-link";import{ChevronRight as O}from"lucide-react";import{jsx as n,jsxs as m}from"react/jsx-runtime";function V(){return m("div",{className:"space-y-8",children:[m("div",{className:"space-y-2",children:[n("h1",{className:"font-bold text-4xl",children:"Spec Signing"}),n("p",{className:"text-lg text-muted-foreground",children:"Signing ensures specs haven't been tampered with and provides an audit trail of all changes."})]}),m("div",{className:"space-y-6",children:[m("div",{className:"space-y-3",children:[n("h2",{className:"font-bold text-2xl",children:"How it works"}),n("p",{className:"text-muted-foreground",children:"Every spec is cryptographically signed before deployment. The signature proves that the spec hasn't been modified since it was signed and creates a permanent record of who deployed it and when."})]}),m("div",{className:"space-y-3",children:[n("h2",{className:"font-bold text-2xl",children:"Signing a spec"}),n("div",{className:"overflow-x-auto rounded-lg border border-border bg-background/50 p-4 font-mono text-muted-foreground text-sm",children:n("pre",{children:`contractspec sign app.spec.ts --key ~/.contractspec/key.pem
contractspec deploy --signed app.spec.ts.signed`})})]}),m("div",{className:"space-y-3",children:[n("h2",{className:"font-bold text-2xl",children:"Verifying signatures"}),n("div",{className:"overflow-x-auto rounded-lg border border-border bg-background/50 p-4 font-mono text-muted-foreground text-sm",children:n("pre",{children:`contractspec verify app.spec.ts.signed
# Output: \u2713 Signature valid
# Signed by: alice@example.com
# Timestamp: 2024-11-08T10:30:00Z`})})]}),n("div",{className:"flex items-center gap-4 pt-4",children:m(E,{href:"/docs/safety/pdp",className:"btn-primary",children:["Next: Policy Decision Points ",n(O,{size:16})]})})]})]})}import{jsx as p,jsxs as f}from"react/jsx-runtime";function U(){return f("div",{className:"space-y-8",children:[f("div",{className:"space-y-4",children:[p("h1",{className:"font-bold text-4xl",children:"Tenant Isolation"}),p("p",{className:"text-lg text-muted-foreground",children:'Preventing cross-tenant data leaks is the #1 security priority for any SaaS. ContractSpec employs "Defense in Depth" to ensure safety.'})]}),f("div",{className:"space-y-4",children:[p("h2",{className:"font-bold text-2xl",children:"Layer 1: RLS Middleware"}),f("p",{children:["The primary defense is the Prisma middleware that rewrites queries to include ",p("code",{children:"WHERE tenantId = ?"}),". This protects against developer error (forgetting to filter)."]})]}),f("div",{className:"space-y-4",children:[p("h2",{className:"font-bold text-2xl",children:"Layer 2: Isolation Validator"}),f("p",{children:["For high-security environments, you can use the"," ",p("code",{children:"IsolationValidator"})," in your test suite to verify that every query generated by your operations actually includes the tenant ID."]}),p("pre",{className:"rounded-lg border bg-muted p-4 text-sm",children:`import { IsolationValidator } from '@contractspec/lib.multi-tenancy/isolation';

test('findUser query is isolated', () => {
  const isValid = IsolationValidator.validateQuery(
    'User',
    'findFirst',
    args,
    'tenant-123'
  );
  expect(isValid).toBe(true);
});`})]}),f("div",{className:"space-y-4",children:[p("h2",{className:"font-bold text-2xl",children:"Layer 3: Policy Engine"}),p("p",{children:"The Policy Decision Point (PDP) verifies that the authenticated user actually belongs to the requested tenant before any operation logic runs."})]})]})}export{U as SafetyTenantIsolationPage,V as SafetySigningPage,q as SafetySecurityTrustPage,A as SafetyPDPPage,D as SafetyOverviewPage,T as SafetyMigrationsPage,P as SafetyAuditingPage};
