---
agentTools:
  projectIndex: https://regscale.readme.io/llms.txt
---

# Archer

## 1. Overview and Prerequisites

The Archer integration is a **one-way pull**: data flows from Archer into RegScale. No writes are made back to Archer.

Three sync commands ship today:

| Command         | What it does                                                                                                                |
| --------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `sync_controls` | Updates ControlImplementation statuses on an existing plan by matching Archer control records to RegScale controls by label |
| `sync_issues`   | Creates or updates RegScale Issues on a plan from Archer findings                                                           |
| `sync_evidence` | Creates or updates tenant-wide RegScale Evidence records from Archer evidence records                                       |

**Prerequisites:**

* RegScale CLI installed and `regscale init` completed (creates `init.yaml`).
* Archer credentials and base URL available.
* Run `regscale archer login` to validate credentials before running sync commands. The login command reads the same `init.yaml` keys and confirms the Archer session token can be obtained.
* The Archer Content API (OData) is used to read application records.

***

## 2. Configuration (`init.yaml`)

Add the following keys to your `init.yaml`. All keys can also be set as environment variables (case-insensitive exact name or `UPPER_SNAKE_CASE`). Environment variables take precedence over `init.yaml` values.

| Key                  | Required | Default                                | Description                                                                                                                                                                                                                                                     |
| -------------------- | -------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `archerBaseUrl`      | Yes      | `https://archer.example.com/RSAarcher` | Base URL of the Archer web application, including the virtual directory (e.g. `/RSAarcher`). No trailing slash.                                                                                                                                                 |
| `archerInstanceName` | Yes      | `Default`                              | Archer instance name. Displayed in the Archer admin console under Instance Configuration.                                                                                                                                                                       |
| `archerUsername`     | Yes      | *(empty)*                              | Archer service-account username. Treated as sensitive — not echoed in logs.                                                                                                                                                                                     |
| `archerPassword`     | Yes      | *(empty)*                              | Archer service-account password. Treated as sensitive — not echoed in logs.                                                                                                                                                                                     |
| `archerUserDomain`   | No       | *(empty)*                              | Windows domain for the service account, when Archer uses Active Directory authentication. Leave blank for local Archer accounts.                                                                                                                                |
| `archerSslVerify`    | No       | `true`                                 | TLS verification mode. Accepted values: `true` (verify using the system CA store) or an absolute path to a CA bundle PEM file (for on-premises Archer deployments with a private CA). The string `false` is **rejected** — TLS verification cannot be disabled. |
| `archerMappingFile`  | No       | *(empty)*                              | Absolute or relative path to a custom mapping JSON file. When empty, the bundled default `mappings/default_archer_mappings.json` is used. Overridden per-run by the `-m` flag.                                                                                  |

**Example `init.yaml` block** (mirrors `init.yaml.example`):

```yaml
archerBaseUrl: https://archer.example.com/RSAarcher
archerInstanceName: Default
archerUsername: ''
archerPassword: ''
archerUserDomain: ''
archerSslVerify: 'true'
archerMappingFile: ''
```

***

## 3. Mapping File

### Resolution Order

The integration resolves the mapping file in priority order (first match wins):

1. **CLI flag** `-m` / `--mapping_file` — explicit path passed at runtime.
2. **`init.yaml`** key `archerMappingFile` — path configured globally.
3. **Bundled default** — `regscale/integrations/commercial/archer/mappings/default_archer_mappings.json` inside the installed package.

### JSON Anatomy

The mapping file is a single JSON object with one top-level key per entity: `controls`, `issues`, `evidence`, and `workflows`. Each entity has three keys:

| Key           | Type   | Description                                                                                                                                                                                     |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `application` | string | The Archer application name to query (e.g. `"Findings"`). Must exactly match the Archer application name.                                                                                       |
| `fields`      | object | Maps a RegScale field key to the Archer field name to read. Example: `"title": "Finding Title"` means "read the Archer field named 'Finding Title' and store it in the RegScale `title` field". |
| `value_maps`  | object | Optional per-field value translation. Each nested key is a RegScale field name; its value is an object mapping Archer display values to RegScale values.                                        |

### Default Mapping

The bundled default (`mappings/default_archer_mappings.json`) assumes standard Archer application and field names. Copy and edit it for customized Archer environments:

```json
{
  "controls": {
    "application": "Controls",
    "fields": {
      "controlId": "Control ID",
      "title": "Control Name",
      "status": "Implementation Status",
      "description": "Control Description"
    },
    "value_maps": {
      "status": {
        "Implemented": "Fully Implemented",
        "Partial": "Partially Implemented",
        "Not Implemented": "Not Implemented"
      }
    }
  },
  "issues": {
    "application": "Findings",
    "fields": {
      "title": "Finding Title",
      "severity": "Severity",
      "status": "Status",
      "description": "Description",
      "dueDate": "Remediation Date"
    },
    "value_maps": {
      "severity": {"Critical": "Critical", "High": "High", "Medium": "Medium", "Low": "Low"},
      "status": {"Open": "Open", "Closed": "Closed"}
    }
  },
  "evidence": {
    "application": "Evidence",
    "fields": {"title": "Title", "description": "Description"},
    "value_maps": {}
  },
  "workflows": {
    "application": "Workflows",
    "fields": {"name": "Workflow Name", "status": "Status"},
    "value_maps": {}
  }
}
```

To customize, copy the file and pass its path via `-m` or set `archerMappingFile` in `init.yaml`.

***

## 4. RegScale Field Reference

### 4.1 Controls → ControlImplementation

**Important behavior:** `sync_controls` **updates** the `status` of ControlImplementations that **already exist** on the plan. It does **not** create new ControlImplementations. Archer control records are matched to existing implementations by control label (the `controlId` field value is matched against the RegScale control's label). Controls present in Archer but not on the plan are logged and skipped.

| Mapping key   | RegScale target field          | Type          | Notes                                                                                                                           |
| ------------- | ------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `controlId`   | control label (match key)      | string        | Used only for lookup — matches an existing ControlImplementation by the control's label on the plan. Not written to the record. |
| `status`      | `ControlImplementation.status` | string (enum) | Required after value-map resolution. Records with a missing or unmapped status are skipped. See valid values below.             |
| `title`       | informational                  | string        | Read from Archer but not currently written to ControlImplementation.                                                            |
| `description` | informational                  | string        | Read from Archer but not currently written to ControlImplementation.                                                            |

**`ControlImplementationStatus` valid values:**

| Enum name              | String value               |
| ---------------------- | -------------------------- |
| `FullyImplemented`     | `Fully Implemented`        |
| `Implemented`          | `Implemented`              |
| `NotImplemented`       | `Not Implemented`          |
| `PartiallyImplemented` | `Partially Implemented`    |
| `InRemediation`        | `In Remediation`           |
| `Inherited`            | `Inherited`                |
| `NA`                   | `Not Applicable`           |
| `Planned`              | `Planned`                  |
| `Archived`             | `Archived`                 |
| `RiskAccepted`         | `Risk Accepted`            |
| `Alternative`          | `Alternate Implementation` |

The value in the `status` field of your mapping file (the right-hand side of the `value_maps.status` object) must be one of the string values above.

***

### 4.2 Issues → Issue

Issues are routed to **create** (new record) or **update** (existing record) by `otherIdentifier`. New records are created with `parentId` = the `-id` plan argument and `parentModule` = `"securityplans"`.

| Mapping key   | RegScale target field | Type              | Notes                                                                                                                                                            |
| ------------- | --------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`       | `Issue.title`         | string            | Issue title.                                                                                                                                                     |
| `severity`    | `Issue.severityLevel` | string (enum)     | Plain values `Critical`, `High`, `Medium`, `Low` are accepted and normalized to the canonical long-form enum strings by the Issue model. See valid values below. |
| `status`      | `Issue.status`        | string (enum)     | See valid values below.                                                                                                                                          |
| `description` | `Issue.description`   | string            | Auto-truncated to 4000 characters (3997 + `"..."`).                                                                                                              |
| `dueDate`     | `Issue.dueDate`       | string (ISO date) | Optional. Example: `2026-12-31`.                                                                                                                                 |

**Auto-set fields (not user-mapped):**

| Field                  | Value                                                |
| ---------------------- | ---------------------------------------------------- |
| `otherIdentifier`      | Archer record ID (dedup + asset-mapping key)         |
| `integrationFindingId` | Archer record ID (matches Issues to Vulnerabilities) |
| `parentId`             | The `-id` plan argument                              |
| `parentModule`         | `"securityplans"` (fixed)                            |

**`IssueSeverity` valid values (canonical long-form):**

| Enum name     | Canonical string value                 | Short alias also accepted |
| ------------- | -------------------------------------- | ------------------------- |
| `Critical`    | `0 - Critical - Must be Fixed`         | `Critical`                |
| `High`        | `I - High - Significant Deficiency`    | `High`                    |
| `Moderate`    | `II - Moderate - Reportable Condition` | `Medium`, `Moderate`      |
| `Low`         | `III - Low - Other Weakness`           | `Low`                     |
| `NotAssigned` | `IV - Not Assigned`                    | `Not Assigned`, `None`    |

Use either the short alias (e.g. `Critical`) or the full canonical string in your `value_maps.severity`. The Issue model normalizes both to the canonical form automatically.

**`IssueStatus` valid values:**

| String value                          |
| ------------------------------------- |
| `Draft`                               |
| `Pending Screening`                   |
| `Open`                                |
| `Pending Verification`                |
| `Closed`                              |
| `Cancelled`                           |
| `Pending Decommission`                |
| `Supply Chain/Procurement Dependency` |
| `Vendor Dependency for Fix`           |
| `Delayed`                             |
| `Exception/Waiver`                    |
| `Pending Approval`                    |

***

### 4.3 Evidence → Evidence

**Important behavior:** RegScale Evidence is **tenant-wide** — it is not scoped to a security plan. The `-id` plan argument is accepted by `sync_evidence` for CLI consistency with the other sync commands, but it does not scope the evidence records created or updated. Evidence is deduplicated by `title` (per-item create-or-update). File attachments are **not** synced (future enhancement — metadata only).

| Mapping key   | RegScale target field  | Type   | Notes                                                                                           |
| ------------- | ---------------------- | ------ | ----------------------------------------------------------------------------------------------- |
| `title`       | `Evidence.title`       | string | Required. Used as the dedup key for create-or-update. Records with a missing title are skipped. |
| `description` | `Evidence.description` | string | Optional.                                                                                       |

***

## 5. Value Maps

The `value_maps` section in the mapping file translates Archer display values to RegScale field values. When a `value_map` exists for a field:

* If the Archer value is in the map, the mapped RegScale value is used.
* If the Archer value is **not** in the map, the record is **logged and skipped** — no default value is substituted.

When no `value_map` exists for a field (the key is absent from `value_maps`), the Archer value is passed through to RegScale unchanged.

**Example: extending a value map**

Suppose your Archer "Findings" application uses a severity field with values `P1`, `P2`, `P3`, `P4`. Add them to the `value_maps.severity` object:

```json
"value_maps": {
  "severity": {
    "P1": "Critical",
    "P2": "High",
    "P3": "Medium",
    "P4": "Low"
  },
  "status": {"Open": "Open", "Closed": "Closed"}
}
```

Any Archer finding with a severity value not in the map (e.g. `P5` or blank) will be logged as unmapped and skipped.

***

## 6. Commands

All Archer commands are under the `archer` group:

```
regscale archer login
regscale archer sync_controls  -id <plan_id>  [-m <mapping_file>]
regscale archer sync_issues    -id <plan_id>  [-m <mapping_file>]
regscale archer sync_evidence  -id <plan_id>  [-m <mapping_file>]
```

### `regscale archer login`

Validates credentials by obtaining an Archer session token. Exits with an error message if authentication fails. Run this first to confirm configuration is correct before running sync commands.

### `regscale archer sync_controls`

```
Options:
  -id, --regscale_ssp_id INTEGER  Target RegScale Security Plan ID.  [required]
  -m, --mapping_file TEXT         Path to a custom Archer mapping JSON (overrides default).
```

Reads control records from the Archer application named in `mapping.controls.application`, matches each to an existing ControlImplementation on the plan by control label, and updates its `status`. Prints a summary on completion:

```
Archer controls synced -- created=0, updated=12, skipped=3
```

`created` is always `0` for controls — this command updates only.

### `regscale archer sync_issues`

```
Options:
  -id, --regscale_ssp_id INTEGER  Target RegScale Security Plan ID.  [required]
  -m, --mapping_file TEXT         Path to a custom Archer mapping JSON (overrides default).
```

Reads finding records from the Archer application named in `mapping.issues.application`. Routes each record to create (new Issue) or update (existing Issue) based on `otherIdentifier` = Archer record ID. Prints a summary:

```
Archer issues synced -- created=5, updated=18, skipped=2
```

### `regscale archer sync_evidence`

```
Options:
  -id, --regscale_ssp_id INTEGER  Target RegScale Security Plan ID (context only — evidence is tenant-wide).  [required]
  -m, --mapping_file TEXT         Path to a custom Archer mapping JSON (overrides default).
```

Reads evidence records from the Archer application named in `mapping.evidence.application`. Creates or updates tenant-wide Evidence records deduplicated by `title`. Because Evidence has no batch endpoint, the create/update split is not reported — all submitted records appear under `created`:

```
Archer evidence synced -- created=8, updated=0, skipped=1
```

***

## 7. Worked Example

**Scenario:** Your Archer instance uses an application called `"Findings"` with field names `"Finding Title"`, `"Priority"` (instead of `"Severity"`), `"Resolution Status"` (instead of `"Status"`), and `"Due Date"`. Priority values are `P1`–`P4`; resolution status values are `Active` and `Resolved`.

**Step 1: Copy the default mapping and customize.**

Save the default JSON to `./my_archer.json` and edit the `issues` section:

```json
{
  "controls": {
    "application": "Controls",
    "fields": {
      "controlId": "Control ID",
      "title": "Control Name",
      "status": "Implementation Status",
      "description": "Control Description"
    },
    "value_maps": {
      "status": {
        "Implemented": "Fully Implemented",
        "Partial": "Partially Implemented",
        "Not Implemented": "Not Implemented"
      }
    }
  },
  "issues": {
    "application": "Findings",
    "fields": {
      "title": "Finding Title",
      "severity": "Priority",
      "status": "Resolution Status",
      "description": "Description",
      "dueDate": "Due Date"
    },
    "value_maps": {
      "severity": {
        "P1": "Critical",
        "P2": "High",
        "P3": "Medium",
        "P4": "Low"
      },
      "status": {
        "Active": "Open",
        "Resolved": "Closed"
      }
    }
  },
  "evidence": {
    "application": "Evidence",
    "fields": {"title": "Title", "description": "Description"},
    "value_maps": {}
  },
  "workflows": {
    "application": "Workflows",
    "fields": {"name": "Workflow Name", "status": "Status"},
    "value_maps": {}
  }
}
```

**Step 2: Run the sync against plan 42.**

```bash
regscale archer sync_issues -id 42 -m ./my_archer.json
```

**Example output:**

```
Archer issues synced -- created=5, updated=18, skipped=2
```

Skipped records (e.g. those with unmapped priority values) are logged at WARNING level with the Archer record ID for investigation.

***

## 8. Idempotency and Re-runs

The integration is safe to re-run. No records are deleted.

| Entity   | Dedup key                                                       | Behavior on re-run                                                                              |
| -------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| Controls | Control label (matched against plan's existing implementations) | Updates `status` on each matched implementation; no creates                                     |
| Issues   | `otherIdentifier` = Archer record ID                            | Creates new Issues for new Archer records; updates existing Issues for already-imported records |
| Evidence | `title`                                                         | Creates new Evidence for new titles; updates existing Evidence for already-imported titles      |

***