{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://fullsend.ai/normative/sandbox-env/v1/harness-env.schema.json",
  "title": "Harness sandbox env contract",
  "description": "Validates the env blocks of a fullsend harness YAML (top-level env, forge.<name>.env, and overlays[].env) against the sandbox environment-variable contract: an env.sandbox key must be a shell variable name and must not be a name the runner reserves, in any letter case, because the runner matches reserved keys case-insensitively and drops them instead of exporting them. Other harness fields are not constrained here. Generated from the runner's code (ADR 0146); see README.md.",
  "type": "object",
  "properties": {
    "env": {
      "$ref": "#/$defs/env_block"
    },
    "forge": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "env": {
            "$ref": "#/$defs/env_block"
          }
        }
      }
    },
    "overlays": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "env": {
            "$ref": "#/$defs/env_block"
          }
        }
      }
    }
  },
  "$defs": {
    "env_block": {
      "type": "object",
      "properties": {
        "sandbox": {
          "$ref": "#/$defs/sandbox_env"
        }
      }
    },
    "sandbox_env": {
      "description": "Variables a harness delivers into the sandbox. The runner owns the reserved names and refuses them here in any letter case.",
      "type": "object",
      "propertyNames": {
        "allOf": [
          {
            "$ref": "#/$defs/env_name"
          },
          {
            "not": {
              "$ref": "#/$defs/reserved_any_case"
            }
          }
        ]
      }
    },
    "env_name": {
      "type": "string",
      "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
    },
    "reserved": {
      "description": "Reserved by the runner: a harness cannot set these through env.sandbox.",
      "enum": [
        "ACTIONS_ID_TOKEN_REQUEST_TOKEN",
        "ACTIONS_ID_TOKEN_REQUEST_URL",
        "ALL_PROXY",
        "BASH_ENV",
        "CDPATH",
        "CURL_CA_BUNDLE",
        "DYLD_INSERT_LIBRARIES",
        "ENV",
        "FULLSEND_FETCH_TOKEN",
        "FULLSEND_FETCH_URL",
        "FULLSEND_GCP_OIDC_AUTH_FILE",
        "FULLSEND_GCP_OIDC_URL",
        "FULLSEND_GCP_PROJECT_ID",
        "FULLSEND_GCP_WIF_PROVIDER",
        "FULLSEND_GITHUB_RUNNER_SECRETS",
        "FULLSEND_GITHUB_RUNNER_SECRETS_FILE",
        "FULLSEND_GITLAB_TRIGGER_ACCOUNT_TOKEN",
        "FULLSEND_INFERENCE_GATEWAY_API_KEY",
        "FULLSEND_ITERATION_DEADLINE",
        "FULLSEND_OPENAI_API_KEY",
        "FULLSEND_OPENAI_AUDIENCE",
        "FULLSEND_OPENAI_IDENTITY_PROVIDER_ID",
        "FULLSEND_OPENAI_SERVICE_ACCOUNT_ID",
        "FULLSEND_OUTPUT_DIR",
        "FULLSEND_OUTPUT_FILE",
        "FULLSEND_OUTPUT_SCHEMA",
        "FULLSEND_PERSONAS_FILE",
        "FULLSEND_ROLE",
        "FULLSEND_RUNNER_PATH",
        "FULLSEND_SLUG",
        "FULLSEND_TARGET_REPO_DIR",
        "FULLSEND_TIMEOUT_MINUTES",
        "FULLSEND_TRIGGER_TOKEN",
        "FULLSEND_WEBHOOK_SECRET",
        "GH_WORKFLOW_TOKEN",
        "GIT_ASKPASS",
        "GIT_CONFIG_GLOBAL",
        "GIT_EXEC_PATH",
        "GIT_SSH_COMMAND",
        "GIT_TEMPLATE_DIR",
        "HOME",
        "HOSTALIASES",
        "HTTPS_PROXY",
        "HTTP_PROXY",
        "IFS",
        "JAVA_TOOL_OPTIONS",
        "LD_AUDIT",
        "LD_LIBRARY_PATH",
        "LD_PRELOAD",
        "NODE_EXTRA_CA_CERTS",
        "NODE_OPTIONS",
        "NO_PROXY",
        "OPENAI_API_KEY",
        "PATH",
        "PERL5OPT",
        "PROMPT_COMMAND",
        "PYTHONPATH",
        "PYTHONSTARTUP",
        "RUBYOPT",
        "SHELL",
        "SSL_CERT_DIR",
        "SSL_CERT_FILE",
        "TRACEPARENT"
      ]
    },
    "reserved_any_case": {
      "description": "The reserved names in any letter case: the runner upper-cases an env.sandbox key before checking it against the reserved set.",
      "pattern": "^(?:[Aa][Cc][Tt][Ii][Oo][Nn][Ss]_[Ii][Dd]_[Tt][Oo][Kk][Ee][Nn]_[Rr][Ee][Qq][Uu][Ee][Ss][Tt]_[Tt][Oo][Kk][Ee][Nn]|[Aa][Cc][Tt][Ii][Oo][Nn][Ss]_[Ii][Dd]_[Tt][Oo][Kk][Ee][Nn]_[Rr][Ee][Qq][Uu][Ee][Ss][Tt]_[Uu][Rr][Ll]|[Aa][Ll][Ll]_[Pp][Rr][Oo][Xx][Yy]|[Bb][Aa][Ss][Hh]_[Ee][Nn][Vv]|[Cc][Dd][Pp][Aa][Tt][Hh]|[Cc][Uu][Rr][Ll]_[Cc][Aa]_[Bb][Uu][Nn][Dd][Ll][Ee]|[Dd][Yy][Ll][Dd]_[Ii][Nn][Ss][Ee][Rr][Tt]_[Ll][Ii][Bb][Rr][Aa][Rr][Ii][Ee][Ss]|[Ee][Nn][Vv]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Ff][Ee][Tt][Cc][Hh]_[Tt][Oo][Kk][Ee][Nn]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Ff][Ee][Tt][Cc][Hh]_[Uu][Rr][Ll]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Gg][Cc][Pp]_[Oo][Ii][Dd][Cc]_[Aa][Uu][Tt][Hh]_[Ff][Ii][Ll][Ee]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Gg][Cc][Pp]_[Oo][Ii][Dd][Cc]_[Uu][Rr][Ll]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Gg][Cc][Pp]_[Pp][Rr][Oo][Jj][Ee][Cc][Tt]_[Ii][Dd]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Gg][Cc][Pp]_[Ww][Ii][Ff]_[Pp][Rr][Oo][Vv][Ii][Dd][Ee][Rr]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Gg][Ii][Tt][Hh][Uu][Bb]_[Rr][Uu][Nn][Nn][Ee][Rr]_[Ss][Ee][Cc][Rr][Ee][Tt][Ss]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Gg][Ii][Tt][Hh][Uu][Bb]_[Rr][Uu][Nn][Nn][Ee][Rr]_[Ss][Ee][Cc][Rr][Ee][Tt][Ss]_[Ff][Ii][Ll][Ee]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Gg][Ii][Tt][Ll][Aa][Bb]_[Tt][Rr][Ii][Gg][Gg][Ee][Rr]_[Aa][Cc][Cc][Oo][Uu][Nn][Tt]_[Tt][Oo][Kk][Ee][Nn]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Ii][Nn][Ff][Ee][Rr][Ee][Nn][Cc][Ee]_[Gg][Aa][Tt][Ee][Ww][Aa][Yy]_[Aa][Pp][Ii]_[Kk][Ee][Yy]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Ii][Tt][Ee][Rr][Aa][Tt][Ii][Oo][Nn]_[Dd][Ee][Aa][Dd][Ll][Ii][Nn][Ee]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Oo][Pp][Ee][Nn][Aa][Ii]_[Aa][Pp][Ii]_[Kk][Ee][Yy]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Oo][Pp][Ee][Nn][Aa][Ii]_[Aa][Uu][Dd][Ii][Ee][Nn][Cc][Ee]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Oo][Pp][Ee][Nn][Aa][Ii]_[Ii][Dd][Ee][Nn][Tt][Ii][Tt][Yy]_[Pp][Rr][Oo][Vv][Ii][Dd][Ee][Rr]_[Ii][Dd]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Oo][Pp][Ee][Nn][Aa][Ii]_[Ss][Ee][Rr][Vv][Ii][Cc][Ee]_[Aa][Cc][Cc][Oo][Uu][Nn][Tt]_[Ii][Dd]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Oo][Uu][Tt][Pp][Uu][Tt]_[Dd][Ii][Rr]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Oo][Uu][Tt][Pp][Uu][Tt]_[Ff][Ii][Ll][Ee]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Oo][Uu][Tt][Pp][Uu][Tt]_[Ss][Cc][Hh][Ee][Mm][Aa]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Pp][Ee][Rr][Ss][Oo][Nn][Aa][Ss]_[Ff][Ii][Ll][Ee]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Rr][Oo][Ll][Ee]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Rr][Uu][Nn][Nn][Ee][Rr]_[Pp][Aa][Tt][Hh]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Ss][Ll][Uu][Gg]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Tt][Aa][Rr][Gg][Ee][Tt]_[Rr][Ee][Pp][Oo]_[Dd][Ii][Rr]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Tt][Ii][Mm][Ee][Oo][Uu][Tt]_[Mm][Ii][Nn][Uu][Tt][Ee][Ss]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Tt][Rr][Ii][Gg][Gg][Ee][Rr]_[Tt][Oo][Kk][Ee][Nn]|[Ff][Uu][Ll][Ll][Ss][Ee][Nn][Dd]_[Ww][Ee][Bb][Hh][Oo][Oo][Kk]_[Ss][Ee][Cc][Rr][Ee][Tt]|[Gg][Hh]_[Ww][Oo][Rr][Kk][Ff][Ll][Oo][Ww]_[Tt][Oo][Kk][Ee][Nn]|[Gg][Ii][Tt]_[Aa][Ss][Kk][Pp][Aa][Ss][Ss]|[Gg][Ii][Tt]_[Cc][Oo][Nn][Ff][Ii][Gg]_[Gg][Ll][Oo][Bb][Aa][Ll]|[Gg][Ii][Tt]_[Ee][Xx][Ee][Cc]_[Pp][Aa][Tt][Hh]|[Gg][Ii][Tt]_[Ss][Ss][Hh]_[Cc][Oo][Mm][Mm][Aa][Nn][Dd]|[Gg][Ii][Tt]_[Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]_[Dd][Ii][Rr]|[Hh][Oo][Mm][Ee]|[Hh][Oo][Ss][Tt][Aa][Ll][Ii][Aa][Ss][Ee][Ss]|[Hh][Tt][Tt][Pp][Ss]_[Pp][Rr][Oo][Xx][Yy]|[Hh][Tt][Tt][Pp]_[Pp][Rr][Oo][Xx][Yy]|[Ii][Ff][Ss]|[Jj][Aa][Vv][Aa]_[Tt][Oo][Oo][Ll]_[Oo][Pp][Tt][Ii][Oo][Nn][Ss]|[Ll][Dd]_[Aa][Uu][Dd][Ii][Tt]|[Ll][Dd]_[Ll][Ii][Bb][Rr][Aa][Rr][Yy]_[Pp][Aa][Tt][Hh]|[Ll][Dd]_[Pp][Rr][Ee][Ll][Oo][Aa][Dd]|[Nn][Oo][Dd][Ee]_[Ee][Xx][Tt][Rr][Aa]_[Cc][Aa]_[Cc][Ee][Rr][Tt][Ss]|[Nn][Oo][Dd][Ee]_[Oo][Pp][Tt][Ii][Oo][Nn][Ss]|[Nn][Oo]_[Pp][Rr][Oo][Xx][Yy]|[Oo][Pp][Ee][Nn][Aa][Ii]_[Aa][Pp][Ii]_[Kk][Ee][Yy]|[Pp][Aa][Tt][Hh]|[Pp][Ee][Rr][Ll]5[Oo][Pp][Tt]|[Pp][Rr][Oo][Mm][Pp][Tt]_[Cc][Oo][Mm][Mm][Aa][Nn][Dd]|[Pp][Yy][Tt][Hh][Oo][Nn][Pp][Aa][Tt][Hh]|[Pp][Yy][Tt][Hh][Oo][Nn][Ss][Tt][Aa][Rr][Tt][Uu][Pp]|[Rr][Uu][Bb][Yy][Oo][Pp][Tt]|[Ss][Hh][Ee][Ll][Ll]|[Ss][Ss][Ll]_[Cc][Ee][Rr][Tt]_[Dd][Ii][Rr]|[Ss][Ss][Ll]_[Cc][Ee][Rr][Tt]_[Ff][Ii][Ll][Ee]|[Tt][Rr][Aa][Cc][Ee][Pp][Aa][Rr][Ee][Nn][Tt])$"
    }
  }
}
