> For the complete documentation index, see [llms.txt](https://docs.balkan.id/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.balkan.id/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup/installation-and-configuration.md).

# Installation & Configuration

Grant the read-only database account, install the agent, and configure it

### Requirements <a href="#requirements" id="requirements"></a>

* **JD Edwards EnterpriseOne 9.2**, the codeline Oracle markets as Release 22 and Release 23.
* **Database platform:**

  | Platform             | Status        | Notes                                                                                   |
  | -------------------- | ------------- | --------------------------------------------------------------------------------------- |
  | Microsoft SQL Server | Supported     | Multiple databases with the JD Edwards owners as schemas; SQL or Windows authentication |
  | Oracle Database      | Supported     | Pure-Go driver, no Instant Client; optional TCPS with a wallet                          |
  | IBM Db2 for i        | Not supported |                                                                                         |
* Network reachability from the agent host to the database listener: TCP `1433` for SQL Server, `1521` for Oracle.
* Outbound HTTPS (`443`) to three BalkanID hostnames:

  | Hostname                       | Used for                                                 |
  | ------------------------------ | -------------------------------------------------------- |
  | `api-integrators.balkanid.app` | resolving your installed integration                     |
  | `balkanid.app`                 | uploading each snapshot                                  |
  | `cdn.balkanid.app`             | installation, the release manifest, and update downloads |
* A dedicated read-only database account (see below). It can be a database username and password, which is the default and the only option on Linux or Oracle. On SQL Server it can instead be the Windows account the service runs as. See [Database authentication](/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup/database-authentication.md).
* BalkanID tenant credentials (`tenant_id`, `tenant_key`, `tenant_secret`) and an installed `jd_edwards` integration on the tenant.
* A Linux (systemd) or Windows host. `root` on Linux or a local Administrator on Windows to install; the agent itself does not run as `root`.
* The release bundle from your BalkanID contact: a `.tar.gz` for Linux or a `.zip` for Windows. It carries the binary, the installer, `config.yaml.example`, and the SQL scripts (`probe-schema.sql`, `grant-mssql.sql`, `grant-oracle.sql`).

***

### Probe the schema <a href="#probe-the-schema" id="probe-the-schema"></a>

Database, owner and column names vary by site. Run `probe-schema.sql` first and use its output for the names below. A wrong owner produces an empty extraction rather than an error.

```powershell
sqlcmd -S <server> -E -i probe-schema.sql -o probe-output.txt -W -s "|" -w 4000
```

### Required database privileges <a href="#required-database-access" id="required-database-access"></a>

Create a dedicated, read-only account. `grant-mssql.sql` and `grant-oracle.sql` create exactly the account below; fill in the variables at the top of the script from the probe output and run it.

Do not grant `SELECT` on `F98OWSEC`. The appendix of each grant script has a view pattern exposing the account-status columns alone.

The account needs `SELECT` on these tables and nothing else. [Insights](/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup.md#insights-and-segregation-of-duties) that depend on an ungranted table are suppressed, never reported clean.

| Tier        | Owner (example)   | Tables                                | Read for                                                                      |
| ----------- | ----------------- | ------------------------------------- | ----------------------------------------------------------------------------- |
| Required    | system `SY920`    | `F0092`, `F95921`, `F00950`, `F0093`  | users and roles, role membership, Security Workbench, environment grants      |
| Recommended | system `SY920`    | `F00926`, `F0094`, `F00941`, `F00942` | role descriptions and `*ALL` sequence, environment master, path code, release |
| Recommended | object `OL920`    | `F9860`                               | object descriptions and product codes                                         |
| Optional    | data `PRODDTA`    | `F0101`, `F01151`, `F0111`            | Address Book names, email addresses, Who's Who                                |
| Optional    | control `PRODCTL` | `F0005`                               | user defined codes                                                            |

**SQL Server.** Grants are per-database, so each database needs its own `USE`, `CREATE USER` and `DENY` block.

```sql
CREATE LOGIN BALKANID_JDE_RO
    WITH PASSWORD = N'<strong-password>',
         DEFAULT_DATABASE = [JDE_SYSTEM],
         CHECK_POLICY = ON;

USE [JDE_SYSTEM];
CREATE USER BALKANID_JDE_RO FOR LOGIN BALKANID_JDE_RO;
GRANT SELECT ON OBJECT::[SY920].[F0092] TO [BALKANID_JDE_RO];   -- repeat per table above
DENY INSERT, UPDATE, DELETE, EXECUTE, ALTER ON SCHEMA::[SY920] TO [BALKANID_JDE_RO];
```

**Oracle.** The four data sources are schemas in one database, so there is no per-database `USE`.

```sql
CREATE USER BALKANID_JDE_RO IDENTIFIED BY "<strong-password>"
  DEFAULT TABLESPACE USERS
  QUOTA 0 ON USERS;
GRANT CREATE SESSION TO BALKANID_JDE_RO;
GRANT SELECT ON SY920.F0092 TO BALKANID_JDE_RO;                 -- repeat per table above
```

On SQL Server, schema discovery needs `VIEW ANY DATABASE`, which is granted to `public` by default. If your build revokes it, name all four databases in the configuration (`system_database`, `object_database`, `data_database`, `control_database`) and the agent searches only those.

**Authentication.** On SQL Server the agent connects either as a SQL login (`db_username` and `db_password`) or with Windows authentication as the account the service runs as (`auth_mode: windows`, Windows hosts only). Oracle uses a username and password. Pick the method before the grant script runs. It decides which principal the grants are made to. See [Database authentication](/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup/database-authentication.md).

***

### Installation <a href="#installation" id="installation"></a>

#### Linux (systemd)

```sh
curl -fsSL https://cdn.balkanid.app/files/balkanid/jd-edwards-agent/releases/latest/install.sh | sudo sh
sudo balkanid-jde-agent --configure          # tenant keys + DB connection
sudo balkanid-jde-agent --test-connection
sudo systemctl restart balkanid-jde-agent
```

The installer verifies the release archive against the published `sha256` checksums, creates the non-login `balkanid` service user, drops the static binary in `/usr/local/bin`, copies the DBA SQL scripts to `/etc/balkanid/jde-agent/scripts/`, and registers and starts the hardened systemd unit.

| Path    | Location                                                                                         |
| ------- | ------------------------------------------------------------------------------------------------ |
| Binary  | `/usr/local/bin/balkanid-jde-agent`                                                              |
| Scripts | `/etc/balkanid/jde-agent/scripts/`                                                               |
| Config  | `/etc/balkanid/jde-agent/config.yaml` (mode `0600`)                                              |
| Output  | `/var/lib/balkanid/jde-agent/output`                                                             |
| Logs    | journald (`journalctl -u balkanid-jde-agent`) + per-day files `/var/log/balkanid/YYYY-MM-DD.log` |
| Unit    | `balkanid-jde-agent.service`                                                                     |

Re-running the installer upgrades in place and leaves configuration, state and logs alone. `--file <path>` installs from a local archive, `--version <tag>` pins a release, `--base-url <url>` points at an internal mirror, and `--no-service` installs the files without registering the unit.

#### Windows (service)

From an **elevated PowerShell**:

```powershell
Invoke-WebRequest -Uri "https://cdn.balkanid.app/files/balkanid/jd-edwards-agent/releases/latest/install.ps1" -OutFile "C:\temp\install.ps1"
C:\temp\install.ps1
& "C:\Program Files\BalkanID\jde-agent\balkanid-jde-agent.exe" --configure
& "C:\Program Files\BalkanID\jde-agent\balkanid-jde-agent.exe" --test-connection
Restart-Service BalkanIDJDEAgent
Get-Service BalkanIDJDEAgent
```

The installer downloads the release `.zip` and verifies its `sha256`, installs the binary to `C:\Program Files\BalkanID\jde-agent\`, copies the DBA SQL scripts and `config.yaml.example` into the install directory, creates the data directory at `C:\ProgramData\BalkanID\jde-agent\`, and registers and starts the Windows service `BalkanIDJDEAgent`.

| Path    | Location                                                                                                            |
| ------- | ------------------------------------------------------------------------------------------------------------------- |
| Binary  | `C:\Program Files\BalkanID\jde-agent\balkanid-jde-agent.exe`                                                        |
| Scripts | `C:\Program Files\BalkanID\jde-agent\scripts\`                                                                      |
| Config  | `C:\ProgramData\BalkanID\jde-agent\config.yaml`                                                                     |
| Output  | `C:\ProgramData\BalkanID\jde-agent\output`                                                                          |
| Logs    | per-day files `C:\ProgramData\BalkanID\jde-agent\logs\YYYY-MM-DD.log`, plus the `BalkanIDJDEAgent` Event Log source |
| Service | `BalkanIDJDEAgent` (auto-start, `LocalSystem` by default)                                                           |

`-File <path>` installs from a local `.zip`, `-Version <tag>` pins a release, `-BaseUrl <url>` points at an internal mirror, and `-NoService` installs the files without registering the service. `-GmsaAccount 'CONTOSO\svc_balkanid_jde$'` or `-ServiceCredential (Get-Credential 'CONTOSO\svc_balkanid_jde')` sets the service identity, which is required for Windows authentication to SQL Server. See [Database authentication](/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup/database-authentication.md).

#### Restrict the directory permissions <a href="#hardening-windows" id="hardening-windows"></a>

Everything under `%ProgramData%` inherits an ACL granting `BUILTIN\Users` read. Restrict both directories after installing. The last line is needed only when the service runs as a domain account or gMSA.

```powershell
$data    = "$env:ProgramData\BalkanID\jde-agent"
$install = "$env:ProgramFiles\BalkanID\jde-agent"

icacls $data /inheritance:r /grant:r "*S-1-5-18:(OI)(CI)F" /grant:r "*S-1-5-32-544:(OI)(CI)F"
icacls $install /inheritance:r /grant:r "*S-1-5-18:(OI)(CI)F" /grant:r "*S-1-5-32-544:(OI)(CI)F" /grant:r "*S-1-5-32-545:(OI)(CI)RX"
icacls $data /grant:r "CONTOSO\svc_balkanid_jde$:(OI)(CI)M"
```

***

### Configuration <a href="#configuration" id="configuration"></a>

The agent resolves its config path in this order. First the `BALKAN_CONFIG_PATH` environment variable. Then the platform default: Linux root `/etc/balkanid/jde-agent/config.yaml`, Linux non-root `~/.config/balkan-cli/config.yaml`, Windows `C:\ProgramData\BalkanID\jde-agent\config.yaml`. Override with `--config <path>`.

The easiest way to configure is the **wizard** (`--configure`), which prompts for the JD Edwards connection and BalkanID credentials, runs a live **Test Connection**, and writes `config.yaml` only on success. It edits the selected instance in place, so a multi-instance file survives. Get the tenant ID/key/secret and integration ID from your BalkanID administrator (Integrations → Add Integration → JD Edwards).

The config file is read at start-up, so restart the service after editing it by hand.

A complete `config.yaml` for extraction. Every key the extraction path accepts appears here, in the position it has to be written in:

```yaml
server:
  heartbeat_mode: true          # run the periodic extract-and-upload loop
  extraction_interval: "2h"     # Go duration string; a nightly site sets "24h"
  requests_interval: "10m"      # write-back poll cadence; ignored while provisioning is off
  provisioning_enabled: false   # write-back; see "Write-back configuration" below

jde:
  instances:
    # A SQL Server instance. Add further instances below; each is extracted and
    # merged into one upload.
    - name: prod-jde            # logical name; becomes the source system on rows
      driver: mssql             # mssql or oracle
      host: jde-sql.internal.example.com   # named instance: host\INSTANCE
      port: 1433                # 1433 for SQL Server, 1521 for Oracle
      auth_mode: sql            # sql, or windows for the service account (Windows hosts only)
      db_username: BALKANID_JDE_RO      # omit both under auth_mode: windows
      db_password: "CHANGE_ME"
      encrypt: true                     # SQL Server TLS
      trust_server_certificate: false   # true for a certificate the host does not trust
      # SQL Server spreads the four data sources across databases:
      system_database: JDE_SYSTEM        # F0092, F95921, F00950, F0093, F0094, F00941, F00942
      object_database: JDE_SYSTEM        # F9860
      data_database: JDE_PRODUCTION      # F0101, F0111, F01151
      control_database: JDE_PRODUCTION   # F0005
      # Schema owners. Blank resolves each one from the database catalog:
      system_owner: ""          # e.g. SY920
      control_owner: ""         # e.g. PRODCTL
      data_owner: ""            # e.g. PRODDTA
      object_owner: ""          # e.g. OL920
      release: "9.2"            # informational; the real value is read from F00942

    # The Oracle alternative. The keys below and the SQL Server keys above never
    # appear on the same instance. Oracle holds the four data sources in one
    # database as schemas, so the *_database keys do not apply. Replace the block
    # above with this one, or keep both as two instances.
    # - name: prod-jde-oracle
    #   driver: oracle
    #   host: jde-ora.internal.example.com
    #   port: 1521
    #   service_name: JDEPROD   # set service_name or sid, never both
    #   sid: ""                 # the alternative to service_name
    #   db_username: BALKANID_JDE_RO
    #   db_password: "CHANGE_ME"
    #   use_tls: true           # Oracle TCPS
    #   wallet_path: "/etc/balkanid/jde-agent/wallet"
    #   system_owner: ""        # e.g. SY920
    #   control_owner: ""       # e.g. PRODCTL
    #   data_owner: ""          # e.g. PRODDTA
    #   object_owner: ""        # e.g. OL920
    #   release: "9.2"

security:
  cnc_principals: [JDE, CNCADMIN]     # administrators to exclude from "held outside CNC" insights
  production_environment_prefixes: [PD, PROD]   # an environment is production when its name starts with one of these
  included_in_all_column: ""          # the F95921 "Include in *ALL" column, from the schema probe
  role_semantics: windows             # windows or web
  disable_insights: false
  disable_sod: false

auth:
  tenant_id: "01xxx"
  tenant_key: ""                # from the BalkanID platform
  tenant_secret: ""             # from the BalkanID platform
  integration_id: ""            # set it when the tenant has more than one JD Edwards integration
```

***

### Configuration reference <a href="#configuration-reference" id="configuration-reference"></a>

Where each key belongs. `jde.instances[]` means the key sits on one instance inside the `jde.instances` list, not at the top level. The write-back keys have [their own table](#write-back-configuration).

| Key                               | Where it goes                              | Default                                                  | What it does                                                                                                       |
| --------------------------------- | ------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `heartbeat_mode`                  | `server.heartbeat_mode`                    | `true` in a generated file, `false` if the key is absent | Runs the extract-and-upload loop. `false` leaves the service idling.                                               |
| `extraction_interval`             | `server.extraction_interval`               | `2h`                                                     | Cadence of the full snapshot. Go duration string. Anything below `30s` is raised to `30s`.                         |
| `requests_interval`               | `server.requests_interval`                 | `10m`                                                    | Cadence of the write-back poll. Same parsing and floor. Ignored while provisioning is off.                         |
| `provisioning_enabled`            | `server.provisioning_enabled`              | `false`                                                  | Gates the write-back loop.                                                                                         |
| `instances`                       | `jde.instances`                            | empty                                                    | The JD Edwards systems to extract. Each one is extracted and merged into a single upload.                          |
| `name`                            | `jde.instances[].name`                     | none, required                                           | Logical name of the instance. Becomes the source system on every emitted row.                                      |
| `driver`                          | `jde.instances[].driver`                   | `mssql`                                                  | `mssql` or `oracle`. IBM Db2 for i is not supported.                                                               |
| `host`                            | `jde.instances[].host`                     | none, required                                           | Database host. A SQL Server named instance goes here as `host\INSTANCE`, with `port` left unset.                   |
| `port`                            | `jde.instances[].port`                     | `1433` on `mssql`, `1521` on `oracle`                    | Listener port.                                                                                                     |
| `auth_mode`                       | `jde.instances[].auth_mode`                | `sql`                                                    | SQL Server only. `windows` authenticates as the account the service runs as, and is rejected at start-up on Linux. |
| `db_username`                     | `jde.instances[].db_username`              | none                                                     | Database login. Required unless `auth_mode` is `windows`.                                                          |
| `db_password`                     | `jde.instances[].db_password`              | none                                                     | Password for `db_username`. Redacted from logs and error messages.                                                 |
| `encrypt`                         | `jde.instances[].encrypt`                  | `true`                                                   | SQL Server TLS.                                                                                                    |
| `trust_server_certificate`        | `jde.instances[].trust_server_certificate` | `false`                                                  | SQL Server only. Accepts the server certificate without hostname or chain validation.                              |
| `system_database`                 | `jde.instances[].system_database`          | discovered from the catalog                              | SQL Server database holding `F0092`, `F95921`, `F00950`, `F0093`, `F0094`, `F00941`, `F00942`. Ignored on Oracle.  |
| `object_database`                 | `jde.instances[].object_database`          | discovered from the catalog                              | SQL Server database holding `F9860`. Ignored on Oracle.                                                            |
| `data_database`                   | `jde.instances[].data_database`            | discovered from the catalog                              | SQL Server database holding `F0101`, `F0111`, `F01151`. Ignored on Oracle.                                         |
| `control_database`                | `jde.instances[].control_database`         | discovered from the catalog                              | SQL Server database holding `F0005`. Ignored on Oracle.                                                            |
| `service_name`                    | `jde.instances[].service_name`             | none                                                     | Oracle only. Set `service_name` or `sid`, not both. One of the two is required on the `oracle` driver.             |
| `sid`                             | `jde.instances[].sid`                      | none                                                     | Oracle only. The alternative to `service_name`.                                                                    |
| `use_tls`                         | `jde.instances[].use_tls`                  | `false`                                                  | Oracle TCPS. Server-certificate verification stays on.                                                             |
| `wallet_path`                     | `jde.instances[].wallet_path`              | none                                                     | Directory holding the Oracle wallet used with `use_tls`.                                                           |
| `system_owner`                    | `jde.instances[].system_owner`             | discovered, then `SY920`                                 | Pins the system-table owner. Blank resolves it from the catalog at connect time.                                   |
| `control_owner`                   | `jde.instances[].control_owner`            | discovered, then `PRODCTL`                               | Pins the control-table owner.                                                                                      |
| `data_owner`                      | `jde.instances[].data_owner`               | discovered, then `PRODDTA`                               | Pins the business-data owner.                                                                                      |
| `object_owner`                    | `jde.instances[].object_owner`             | discovered, then `OL920`                                 | Pins the object-librarian owner.                                                                                   |
| `release`                         | `jde.instances[].release`                  | `9.2`                                                    | Informational. The real value is read from `F00942`.                                                               |
| `cnc_principals`                  | `security.cnc_principals`                  | empty                                                    | User IDs and role names treated as legitimate administrators.                                                      |
| `production_environment_prefixes` | `security.production_environment_prefixes` | `[PD, PROD]`                                             | An environment is classified production when its name starts with one of these.                                    |
| `included_in_all_column`          | `security.included_in_all_column`          | empty                                                    | The `F95921` column carrying the P95921 "Include in \*ALL" checkbox.                                               |
| `role_semantics`                  | `security.role_semantics`                  | `windows`                                                | `windows` or `web`. Which client the effective-access resolution models.                                           |
| `disable_insights`                | `security.disable_insights`                | `false`                                                  | Turns off insight generation.                                                                                      |
| `disable_sod`                     | `security.disable_sod`                     | `false`                                                  | Turns off the Segregation of Duties matrix.                                                                        |
| `tenant_id`                       | `auth.tenant_id`                           | none, required                                           | Your BalkanID tenant identifier.                                                                                   |
| `tenant_key`                      | `auth.tenant_key`                          | none, required                                           | Tenant API key.                                                                                                    |
| `tenant_secret`                   | `auth.tenant_secret`                       | none, required                                           | Tenant API secret. Redacted from logs and error messages.                                                          |
| `integration_id`                  | `auth.integration_id`                      | empty                                                    | Which JD Edwards integration receives the upload. See below.                                                       |

***

### Which integration receives the data <a href="#which-integration-receives-the-data" id="which-integration-receives-the-data"></a>

`auth.integration_id` decides where each snapshot lands.

Left blank, the agent queries the tenant's installed apps at upload time and takes the first entry whose `appId` matches `jd_edwards`. It does not count the matches and does not check for ambiguity.

| The tenant has                                                                    | With `auth.integration_id` blank                                                                  |
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Exactly one JD Edwards integration                                                | It resolves to that integration.                                                                  |
| More than one, for example a proof-of-concept integration beside a production one | It resolves to whichever the API returns first, and a full snapshot uploads into it. Set the key. |
| No JD Edwards integration                                                         | The cycle fails with `jd_edwards integration not found for tenant`.                               |

Set explicitly, the lookup is skipped and every snapshot goes to that integration.

Get the value from your BalkanID administrator, from the JD Edwards integration under **Integrations** in the BalkanID platform.

On `jd_edwards integration not found for tenant`, install the integration on the tenant, or set `auth.integration_id`.

***

### The `security` block <a href="#the-security-block" id="the-security-block"></a>

These keys decide how [insights](/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup.md#insights-and-segregation-of-duties) are computed. The values are site-specific, so review them before the first extraction anyone will read.

| Key                               | What it sets                                                                                                                                                                                                                                                                                                                                                                                | If it is wrong or left at the default                                                                                                                                                                                                   | Where the value comes from                                                                            |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `cnc_principals`                  | The user IDs and role names that are legitimately administrators. Several insights ask whether an administrative application is reachable outside the CNC team.                                                                                                                                                                                                                             | Left empty, those insights name your own CNC team as the largest exposure in the tenant. The insights are still produced and are annotated as unfiltered. Fill this in before anyone reviews the results.                               | Your CNC team's EnterpriseOne user IDs, plus the administrative role names they sign on with.         |
| `production_environment_prefixes` | An environment is classified production when its name starts with one of these. The classification drives the listing of who is authorised to Production, and the [Segregation of Duties](/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup.md#insights-and-segregation-of-duties) rules that apply only there. | Defaults to `PD` and `PROD`. If your production environment is called something else, for example `JPD920`, add its prefix, or those controls report nothing and look clean.                                                            | Take the names from the environment master (`F0094`) or from your CNC team.                           |
| `included_in_all_column`          | The `F95921` column holding the P95921 "Include in \*ALL" checkbox. Its name varies by release.                                                                                                                                                                                                                                                                                             | Left empty, the flag is absent from the role assignments and nothing else changes. A name that is not a column of `F95921` is logged and ignored.                                                                                       | Section 4 of `probe-schema.sql`, which reports the spelling your site uses.                           |
| `role_semantics`                  | Which client the effective-access resolution models, `windows` or `web`. Defaults to `windows`.                                                                                                                                                                                                                                                                                             | Signing on as `*ALL` evaluates every included role on the Windows client. The web client by default consults only the first role in sequence order, so `web` on a Windows-client site under-reports the access every `*ALL` user holds. | Your CNC team, from the client your users sign on with. The agent cannot read this from the database. |
| `disable_insights`                | Turns off insight generation. Extraction is unaffected.                                                                                                                                                                                                                                                                                                                                     | `false` leaves insights on. Set to `true`, the upload carries the access graph and no insights.                                                                                                                                         | Leave at `false` unless BalkanID support asks otherwise.                                              |
| `disable_sod`                     | Turns off the Segregation of Duties matrix. Extraction is unaffected.                                                                                                                                                                                                                                                                                                                       | `false` leaves the matrix on. Set to `true`, the other insights are still produced.                                                                                                                                                     | Leave at `false` unless BalkanID support asks otherwise.                                              |

`production_environment_prefixes` is a prefix match on the environment name:

| Environments              | Prefixes     | Classified production |
| ------------------------- | ------------ | --------------------- |
| `PD920`, `PY920`, `DV920` | `[PD, PROD]` | `PD920`               |
| `JPD920`, `TEST920`       | `[PD, PROD]` | nothing               |

***

### Connecting over TLS <a href="#connecting-over-tls" id="connecting-over-tls"></a>

Every key here is per instance, under `jde.instances[]`.

On SQL Server `encrypt` defaults to `true`, so the agent host must trust the certificate the database presents, and the name in `host:` must appear in the certificate's Subject Alternative Name list. Import the issuing CA into the host trust store (`update-ca-trust` or `update-ca-certificates` on Linux, `Cert:\LocalMachine\Root` on Windows), or set `jde.instances[].trust_server_certificate: true` on that instance. On Oracle, TCPS is `jde.instances[].use_tls: true` with the trust anchors supplied as an Oracle wallet at `jde.instances[].wallet_path`; server-certificate verification stays on.

***

### Write-back configuration <a href="#write-back-configuration" id="write-back-configuration"></a>

The `server.provisioning` block is **optional**. Omit it and the agent is extraction-only. Extraction never reads through AIS and never needs any key in this section.

`server.provisioning.mode` defaults to `dry-run`. A block that is present but incomplete sends nothing. See [Provisioning (write-back)](/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup/running-the-agent.md#provisioning-write-back) for what the agent can and cannot apply.

```yaml
server:
  provisioning_enabled: true    # top level, outside the provisioning block
  provisioning:
    # Connection
    ais_base_url: "https://jde-ais.internal.example.com:9302"   # /jderest is appended
    ais_username: "BALKANID_PROV"
    ais_password: "CHANGE_ME"
    ais_device_name: "balkanid-jde-agent"   # accepted, not used
    ais_timeout: "30s"
    allow_insecure: false

    # What may be attempted
    mode: dry-run               # dry-run or enforce
    allowed_operations:
      - grant_role
      - grant_environment
      - revoke_environment

    # Blast radius
    max_changes_per_cycle: 10
    max_change_fraction: 0.02
    max_extraction_age: "26h"
    allowed_seeded_profiles: []

    # Your site's own contract
    orchestrations:
      grant_role: "BALKANID_GRANT_ROLE"
      grant_environment: "BALKANID_GRANT_ENV"
      revoke_environment: "BALKANID_REVOKE_ENV"
    input_names:
      user: "User"
      role: "Role"
      environment: "Environment"
      effective_date: "EffectiveDate"
    date_format: "01/02/2006"   # a Go layout string; see the table below

    # Drift pins
    contract_fingerprint: ""
    declared_fingerprint: ""
```

| Key                       | Where it goes                                 | Default   | What it does                                                                                                                                                                            |
| ------------------------- | --------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ais_base_url`            | `server.provisioning.ais_base_url`            | none      | Scheme, host and port of the AIS server. `/jderest` is appended when the URL carries no path. Required for enforcement.                                                                 |
| `ais_username`            | `server.provisioning.ais_username`            | none      | The EnterpriseOne user the agent signs in to AIS as. The agent refuses to provision access for this account. Required for enforcement.                                                  |
| `ais_password`            | `server.provisioning.ais_password`            | none      | Password for `ais_username`. Redacted from logs and error messages. Required for enforcement.                                                                                           |
| `ais_device_name`         | `server.provisioning.ais_device_name`         | none      | Accepted and not used. The agent identifies itself to AIS as `balkanid-jde-agent`.                                                                                                      |
| `ais_timeout`             | `server.provisioning.ais_timeout`             | `30s`     | Go duration string bounding one AIS call.                                                                                                                                               |
| `allow_insecure`          | `server.provisioning.allow_insecure`          | `false`   | Permits an `http://` `ais_base_url`. Certificate verification is not affected; a self-signed AIS certificate goes in the agent host's trust store.                                      |
| `mode`                    | `server.provisioning.mode`                    | `dry-run` | `dry-run` plans and audits and transmits nothing. `enforce` is the only value that transmits. Any other value resolves to `dry-run` and is logged at start-up.                          |
| `allowed_operations`      | `server.provisioning.allowed_operations`      | empty     | Which operations may be attempted. Valid entries are `grant_role`, `grant_environment` and `revoke_environment`. Empty permits nothing. `revoke_role` is refused even when listed.      |
| `max_changes_per_cycle`   | `server.provisioning.max_changes_per_cycle`   | `10`      | Absolute cap on changes acted on in one cycle.                                                                                                                                          |
| `max_change_fraction`     | `server.provisioning.max_change_fraction`     | `0.02`    | Cap as a fraction of the extracted access population, which is the role assignments plus the environment grants. Clamped to `1`.                                                        |
| `max_extraction_age`      | `server.provisioning.max_extraction_age`      | `26h`     | Go duration string. Past this age the whole batch is refused rather than admitted against a stale extraction.                                                                           |
| `allowed_seeded_profiles` | `server.provisioning.allowed_seeded_profiles` | empty     | Oracle-shipped profiles this site may provision. Empty refuses all of them. Recognised: `JDE`, `JDEDBA`, `JDESEC`, `DEMO`, `DEVUSER`, `TESTUSER`, `PSFT`, `MODEL`, `OWTOOL`, `SUPPORT`. |
| `orchestrations`          | `server.provisioning.orchestrations`          | empty     | Maps an operation to the orchestration name that performs it at your site. No defaults. An allowed operation that names none blocks enforcement.                                        |
| `input_names`             | `server.provisioning.input_names`             | empty     | Maps the agent's field names to the input names your orchestration declares, case-sensitively. Keys are `user`, `role`, `environment`, `effective_date` and `expiration_date`.          |
| `date_format`             | `server.provisioning.date_format`             | none      | The Go layout string the effective date is rendered with. Required for enforcement.                                                                                                     |
| `contract_fingerprint`    | `server.provisioning.contract_fingerprint`    | empty     | Pins the orchestration names, input names and date format in this file. A mismatch blocks enforcement. `--plan` prints the current value.                                               |
| `declared_fingerprint`    | `server.provisioning.declared_fingerprint`    | empty     | Pins the contract the AIS server declares. Empty is unpinned. `--check-ais` prints the value to pin. Not interchangeable with `contract_fingerprint`.                                   |

The effective per-cycle budget is the lesser of `max_changes_per_cycle` and `max_change_fraction`. The excess is deferred to the next cycle rather than dropped.

`input_names.expiration_date` is accepted and never sent. `effective_date` is sent on `grant_role` and `grant_environment`, and only when `input_names` maps it.

**`date_format` is a Go layout string**, written with the reference date `Mon Jan 2 15:04:05 MST 2006`, not a pattern of `Y`/`M`/`D` letters. `MM/DD/YYYY` is refused at plan time.

| Your orchestration expects | Write        |
| -------------------------- | ------------ |
| `MM/DD/YYYY`               | `01/02/2006` |
| `DD/MM/YYYY`               | `02/01/2006` |
| `YYYY-MM-DD`               | `2006-01-02` |

***

### Verify the connection <a href="#verify-the-connection" id="verify-the-connection"></a>

```sh
balkanid-jde-agent --test-connection
```

Prints the resolved schema owners, the EnterpriseOne release read from `F00942`, visible row counts and per-table readability.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.balkan.id/getting-started/setting-up-your-tenant/application-integrations/direct-application-integrations/jd-edwards-integration-setup/installation-and-configuration.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
