{
  "schema": "hasna.service_contract.v1",
  "name": "instructions",
  "class": "service",
  "contractVersion": "v1",
  "kitVersion": "1.3.8",
  "description": "AI coding agent instruction & configuration manager (formerly @hasna/configs). CLI + MCP + HTTP API (instructions-serve) + generated SDK at the ./sdk export. The CLI, the MCP server and the SDK are hosted-by-default clients of the /v1 API: each call resolves its API key and authority through the one @hasna/contracts client chain (HASNA_INSTRUCTIONS_API_KEY / HASNA_INSTRUCTIONS_API_URL, the macOS Keychain item hasna.credentials.instructions.api-key, ~/.hasna/instructions/config/credentials, default https://api.hasna.com/instructions) and fails closed with no credential; the on-box sqlite store is opened only by the explicit opt-in HASNA_INSTRUCTIONS_LOCAL=1. The hosted /v1 server requires postgresql through HASNA_INSTRUCTIONS_DATABASE_URL and reports unconfigured/503 without it; it never exposes the local SQLite file. The serve process reads/writes the shared Postgres directly with API-key auth via @hasna/contracts. The MCP server keeps the legacy name 'configs' aliased for the existing fleet. Optional native S3 support stores immutable, digest-verified export backups as an adjunct plane and never selects a database or client transport.",
  "bins": [
    "instructions",
    "instructions-mcp",
    "instructions-serve",
    "configs",
    "configs-mcp"
  ],
  "hosting": [
    "user-hosted",
    "hasna-saas"
  ],
  "serviceSurfaces": [
    {
      "name": "http-api",
      "kind": "api",
      "status": "supported",
      "bin": "instructions-serve",
      "authMode": "api-key",
      "health": {
        "method": "GET",
        "path": "/health",
        "public": true
      },
      "readiness": {
        "method": "GET",
        "path": "/ready",
        "public": true
      },
      "version": {
        "method": "GET",
        "path": "/version",
        "public": true
      },
      "apiBasePath": "/v1",
      "openApiPath": "/openapi.json"
    },
    {
      "name": "typescript-sdk",
      "kind": "sdk",
      "status": "supported",
      "authMode": "api-key",
      "exportSubpath": "./sdk",
      "generatedFrom": "/openapi.json"
    },
    {
      "name": "cli",
      "kind": "cli",
      "status": "supported",
      "bin": "instructions",
      "authMode": "api-key"
    },
    {
      "name": "mcp",
      "kind": "mcp",
      "status": "supported",
      "mcpBin": "instructions-mcp",
      "authMode": "api-key"
    }
  ],
  "storage": {
    "backend": "sqlite",
    "engines": [
      "sqlite",
      "postgresql"
    ],
    "envPrefix": "HASNA_INSTRUCTIONS_",
    "aliasEnvPrefix": "INSTRUCTIONS_",
    "sqlitePath": "~/.hasna/instructions/instructions.db",
    "pgTestGate": {
      "envVar": "HASNA_INSTRUCTIONS_TEST_DATABASE_URL",
      "command": "bun run test:postgres"
    }
  },
  "metadata": {
    "service": {
      "port": 8080,
      "healthPath": "/health",
      "readyPath": "/ready",
      "versionPath": "/version",
      "openapiPath": "/openapi.json",
      "apiVersion": "v1",
      "auth": "api-key"
    },
    "client": {
      "apiUrlEnv": "HASNA_INSTRUCTIONS_API_URL",
      "apiKeyEnv": "HASNA_INSTRUCTIONS_API_KEY"
    },
    "mcp": {
      "name": "configs",
      "note": "MCP server identity intentionally kept as 'configs' so the 17-machine fleet MCP config keeps working; fleet rename is a separate controlled step."
    },
    "release": {
      "artifactScan": {
        "script": "scan:artifact"
      }
    }
  },
  "serving": {
    "routeSlug": "instructions",
    "access": "api-key",
    "targetClientBase": "https://api.hasna.com/instructions"
  }
}
