# Component: Inbound API

## Purpose

The Inbound API exposes a web API on the central cluster that external systems can call into. This is the reverse of the External System Gateway — where that component handles the SCADA system calling out to external systems, this component handles external systems calling in. It provides API key authentication, method-level authorization, and script-based method implementations.

## Location

Central cluster only (active node). Not available at site clusters.

## Responsibilities

- Host a web API endpoint on the central cluster.
- Authenticate inbound requests via API keys.
- Route requests to the appropriate API method definition.
- Enforce per-method API key authorization (only approved keys can call a given method).
- Execute the C# script implementation for the called method.
- Return structured responses to the caller.
- Failover: API becomes available on the new active node after central failover.

## API Key Management

### Storage
- API keys are stored in the **configuration database (MS SQL)**.

### Key Properties
- **Name/Label**: Human-readable identifier for the key (e.g., "MES-Production", "RecipeManager-Dev").
- **Key Value**: The secret key string used for authentication.
- **Enabled/Disabled Flag**: Keys can be disabled without deletion.

### Management
- Managed by users with the **Admin** role via the Central UI.
- All key changes (create, enable/disable, delete) are audit logged.

## API Method Definition

### Properties
Each API method definition includes:
- **Method Name**: Unique identifier and URL path segment for the endpoint.
- **Approved API Keys**: List of API keys authorized to invoke this method. Requests from non-approved keys are rejected.
- **Parameter Definitions**: Ordered list of input parameters, each with:
  - Parameter name.
  - Data type (Boolean, Integer, Float, String — same fixed set as template attributes).
- **Return Value Definition**: Structure of the response, with:
  - Field names and data types. Supports returning **lists of objects**.
- **Implementation Script**: C# script that executes when the method is called. Stored **inline** in the method definition. Follows standard C# authoring patterns but has no template inheritance — it is a standalone script tied to this method.
- **Timeout**: Configurable per method. Defines the maximum time the method is allowed to execute (including any routed calls to sites) before returning a timeout error to the caller.

### Management
- Managed by users with the **Design** role via the Central UI.
- All method definition changes are audit logged.

## HTTP Contract

### URL Structure
- All API calls use `POST /api/{methodName}`.
- Method names map directly to URL path segments (e.g., method "GetProductionReport" → `POST /api/GetProductionReport`).
- All calls are POST — these are RPC-style script invocations, not RESTful resource operations.

### API Key Header
- API key is passed via the `X-API-Key` HTTP header.

### Request Format
- Content-Type: `application/json`.
- Parameters are top-level JSON fields in the request body matching the method's parameter definitions:
```json
{
  "siteId": "SiteA",
  "startDate": "2026-03-01",
  "endDate": "2026-03-16"
}
```

### Response Format
- **Success (200)**: The response body is the method's return value as JSON, with fields matching the return value definition:
```json
{
  "siteName": "Site Alpha",
  "totalUnits": 14250,
  "lines": [
    { "lineName": "Line-1", "units": 8200, "efficiency": 92.5 },
    { "lineName": "Line-2", "units": 6050, "efficiency": 88.1 }
  ]
}
```
- **Failure (4xx/5xx)**: The response body is an error object:
```json
{
  "error": "Site unreachable",
  "code": "SITE_UNREACHABLE"
}
```
- HTTP status codes distinguish success from failure — no envelope wrapper.

### Extended Type System
- API method parameter and return type definitions support an **extended type system** beyond the four template attribute types (Boolean, Integer, Float, String):
  - **Object**: A named structure with typed fields. Supports nesting.
  - **List**: An ordered collection of objects or primitive types.
- This allows complex request/response structures (e.g., an object containing properties and a list of nested objects).
- Template attributes retain the simpler four-type system. The extended types apply only to Inbound API method definitions and External System Gateway method definitions.

## Script Compilation & Hot-Reload

API method scripts are compiled at central startup — all method definitions are loaded from the configuration database and compiled into in-memory delegates.

### Update Workflow

- Updating a method via the CLI (`api-method update --id <N> --code '...'`) or Management API triggers immediate recompilation (`CompileAndRegister`). The updated script takes effect on the next API call — no node restart is required.
- Creating a new method after startup: if the method is created but not yet compiled, the first invocation triggers lazy (on-demand) compilation.

### Direct SQL Warning

> **Do not edit API method scripts via direct SQL.** The in-memory compiled script will not be updated until the next node restart. Always use the CLI, Management API, or Central UI to modify API method scripts.

---

## API Call Logging

- **Every request — success or failure — emits one `ApiInbound.Completed` row** to `ICentralAuditWriter` from request middleware before the HTTP response is flushed. The row captures the API key **name** (never the key material), remote IP, user-agent, response status, duration, and truncated request/response bodies per the Audit Log capture policy (see Component-AuditLog.md, Payload Capture Policy). This supersedes the earlier failures-only stance: operational API traffic is now part of the centralized audit log, so configuration changes and call activity share a single retention/query surface.
- Script execution errors (500 responses) remain captured on the same `ApiInbound.Completed` row (response status + error fields) rather than emitting a separate failure-only event.
- **Non-blocking semantics.** Middleware audit-write failures are logged and metricked (see Health Monitoring #11 — `CentralAuditWriteFailures`) but **never affect the HTTP response**: a failed audit append does not turn a successful API call into an error returned to the caller.
- No rate limiting — this is a private API in a controlled industrial environment with a known set of callers. Misbehaving callers are handled operationally (disable the API key).

## Request Flow

```
External System
    │
    ▼
Inbound API (Central)
    ├── 1. Extract API key from request
    ├── 2. Validate key exists and is enabled
    ├── 3. Resolve method by name
    ├── 4. Check API key is in method's approved list
    ├── 5. Validate and deserialize parameters
    ├── 6. Execute implementation script (subject to method timeout)
    ├── 7. Serialize return value
    └── 8. Return response
```

## Implementation Script Capabilities

The C# script that implements an API method executes on the central cluster. Unlike instance scripts at sites, inbound API scripts run on central and can interact with **any instance at any site** through a routing API.

Inbound API scripts **cannot** call shared scripts directly — shared scripts are deployed to sites only and execute inline in Script Actors. To execute logic on a site, use `Route.To().Call()`.

### Script Runtime API

#### Instance Routing
- `Route.To("instanceUniqueCode").Call("scriptName", parameters)` — Invoke a script on a specific instance at any site. Central routes the call to the appropriate site via the Communication Layer. The call reaches the target Instance Actor's Script Actor, which spawns a Script Execution Actor to execute the script. The return value flows back to the calling API script.
- `Route.To("instanceUniqueCode").GetAttribute("attributeName")` — Read a single attribute value from a specific instance at any site.
- `Route.To("instanceUniqueCode").GetAttributes("attr1", "attr2", ...)` — Read multiple attribute values in a **single call**, returned as a dictionary of name-value pairs.
- `Route.To("instanceUniqueCode").SetAttribute("attributeName", value)` — Write a single attribute value on a specific instance at any site.
- `Route.To("instanceUniqueCode").SetAttributes(dictionary)` — Write multiple attribute values in a **single call**, accepting a dictionary of name-value pairs.

#### Input/Output
- **Input parameters** are available as defined in the method definition.
- **Return value** construction matching the defined return structure.

#### Parameter Access
- `Parameters["key"]` — Raw dictionary access.
- `Parameters.Get<T>("key")` — Typed access (same API as site runtime scripts). See Site Runtime component for full type support.

> **No direct database access.** Inbound API scripts are not given a raw database
> client. Handing a script a raw `SqlConnection` is in direct tension with the
> ScadaLink script trust model (scripts are forbidden `System.IO`, `Process`,
> `Threading`, `Reflection`, and raw network access; `ForbiddenApiChecker`
> statically enforces this). Scripts interact with the system only through the
> curated `Route` and `Parameters` surfaces above. If a method needs data from
> the configuration or machine-data databases, that access belongs behind a
> dedicated, scoped helper — not a general-purpose connection — and would be
> added here as an explicit design change.

### Routing Behavior
- The `Route.To()` helper resolves the instance's site assignment from the configuration database and routes the request to the correct site cluster via the Communication Layer.
- The call is **synchronous from the API caller's perspective** — the API method blocks until the site responds or the **method-level timeout** is reached.
- If the target site is unreachable or the call times out, the call fails and the API returns an error to the caller. No store-and-forward buffering is used for inbound API calls.

## Authentication Details

- API key is passed via the `X-API-Key` HTTP header.
- The system validates:
  1. The key exists in the configuration database.
  2. The key is enabled.
  3. The key is in the approved list for the requested method.
- Failed authentication returns an appropriate HTTP error (401 Unauthorized or 403 Forbidden).

## Error Handling

- Invalid API key → 401 Unauthorized.
- Valid key but not approved for method → 403 Forbidden.
- Invalid parameters → 400 Bad Request.
- Script execution failure → 500 Internal Server Error (with safe error message, no internal details exposed).
- Script errors are logged in the central audit/event system.

## Dependencies

- **Configuration Database (MS SQL)**: Stores API keys and method definitions.
- **Communication Layer**: Routes requests to sites when method implementations need site data.
- **Security & Auth**: API key validation (separate from LDAP/AD — API uses key-based auth).
- **Configuration Database (via IAuditService)**: All API key and method definition changes are audit logged.
- **Audit Log (#23)**: Every inbound API request emits an `ApiInbound.Completed` row via `ICentralAuditWriter` from request middleware (non-blocking for the HTTP response). Payload truncation/redaction follows the Audit Log Payload Capture Policy.
- **Cluster Infrastructure**: API is hosted on the active central node and fails over with it.

## Interactions

- **External Systems**: Call the API with API keys.
- **Communication Layer**: API method scripts use this to reach sites.
- **Site Runtime (Instance Actors, Script Actors)**: Routed calls execute on site Instance Actors via their Script Actors.
- **Central UI**: Admin manages API keys; Design manages method definitions.
- **Configuration Database (via IAuditService)**: Configuration changes are audited.
