> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://cla-demo.postmansolutions.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://cla-demo.postmansolutions.com/_mcp/server.

# Design Overview

## 1. New Schema: `[extractor].[Job]`

We will introduce a new SQL schema to track extractor job executions.

### Table: `[extractor].[Job]`

| Column Name                    | Type               | Description                                                   |
| ------------------------------ | ------------------ | ------------------------------------------------------------- |
| `JobID`                        | `UNIQUEIDENTIFIER` | Globally unique ID for this extraction job                    |
| `FileID`                       | `UNIQUEIDENTIFIER` | FK to `[file].[File]`                                         |
| `ClientApplicationExtractorID` | `INT`              | FK to `[registration].[ClientApplicationExtractor]`           |
| `Status`                       | `VARCHAR(50)`      | Enum: `Queued`, `Started`, `Succeeded`, `Failed`, `Cancelled` |
| `StatusMessage`                | `VARCHAR(MAX)`     | Optional error or info message                                |
| `CreatedAt`                    | `DATETIMEOFFSET`   | When job was created                                          |
| `UpdatedAt`                    | `DATETIMEOFFSET`   | When last status change occurred                              |
| `CompletedAt`                  | `DATETIMEOFFSET`   | When job finished (nullable)                                  |
| `ExtractorResponse`            | `NVARCHAR(MAX)`    | Raw JSON from extractor (optional)                            |

#### Indexes

* IX\_FileID
* IX\_ClientApplicationExtractorID
* IX\_Status

---

## 2. Lifecycle Flow

### Trigger: File Accepted

* File arrives and is written to Blob Storage
* `FileAccepted` message is published to `TOPIC_ACCEPTED_FILE`

### Step 1: Extractor Service Receives Message

* Lookup `ClientApplicationID` associated with file
* Call `GET /registration/:clientAppId/extractors` (new endpoint)
* Receive array of active extractors (filtered on `IsActive = true`)

### Step 2: Start First Extractor (MVP scope)

* Pick the first extractor from the list
* Generate new `JobID` (UUID)
* Call extractor's `ExtractionUrl` with:

```json
{
  "fileUrl": "<signed blob url>",
  "jobId": "<JobID>"
}
```

* Insert new record into `[extractor].[Job]` with status `Queued`
* Publish `JobQueued` message to `TOPIC_JOB_STATUS`

---

## 3. Service Bus Messaging

### Messages from Extractor

All status transitions publish messages to Service Bus, consumed by the Status service:

| Message Type   | Fields                                        |
| -------------- | --------------------------------------------- |
| `JobQueued`    | `JobID`, `FileID`, `ExtractorID`, `Timestamp` |
| `JobStarted`   | `JobID`, `Timestamp`                          |
| `JobSucceeded` | `JobID`, `Timestamp`, `ResultSummary`         |
| `JobFailed`    | `JobID`, `Timestamp`, `ErrorMessage`          |

All use a consistent envelope structure already understood by the Status service.

---

## 4. Registration Endpoint

### Route: `GET /registration/:clientAppId/extractors`

Returns:

```json
[
  {
    "clientApplicationExtractorId": 101,
    "extractionUrl": "https://..."
  }
]
```

* Filters by `IsActive = true`
* Used by the Extractor service to determine which jobs to start

---

## 5. Security & Access

* Extractor service must have DB write access to `[extractor]` schema
* Extractor uses existing `registration.apiClient.ts` to call Registration service
* Service Bus message schema will be versioned and appended to platform docs