Merge pull request 'Phase 12: Audit trail' (#13) from docs/phase-12-audit-trail into main

Reviewed-on: cliu/ci-server-config#13
This commit is contained in:
Clio Liu 2026-10-01 17:38:24 +10:00
commit 7cff9d4aa4
16 changed files with 555 additions and 12 deletions

View file

@ -0,0 +1,39 @@
---
name: audit-trail
description: >-
CI Server R1.03 AUDIT Service and audit trail. Use when the user wants to know who changed
what and when (item value written, limit or description changed, item / section / object /
report inserted or deleted, login, logout, failed login, alarm acknowledged or shelved), read
or export the audit trail (AUDIT_TRAIL dataset, storage group ADT, old value / new value, user,
source HMI / LOC-ENG-MOD / ENT-ENG-MOD / OPER-INTERFACE / ODBC / QUICKLOAD), make an audit
report, switch auditing of an event type on or off (event classifiers, AUDIT_EVENT_CLAS_DF,
STORAGE, "Audit trailing wanted" / AUDIT_INFO on an item), filter audit events (selection
groups, AUDIT_SELGRP_DF, expression sbid / sbgp / user / nval), print or log audit events
(ADTLOG event logger, adtsys.sup, E_LAYOUT, SEL_GROUP), check AUDIT Service (adtsto, adtcol,
adtdst, audit_start), or change how long the audit trail is kept (ADT lifetime). Source
IM 36K10L25-01EN.
---
# Audit trail (R1.03)
Background: `knowledge/manuals/IM36K10L25-01EN.md` (processes, classifiers, setup keywords,
installed findings), `IM36K10G10-01EN.md` ch. 9 (overview), `IM36K10C40-01EN.md` (storage groups),
`IM36K10P20-01EN.md` (RQL for audit reports).
Rules:
- Run `system-check` first; follow the user's chosen way of working.
- The audit trail is evidence: single records cannot be deleted, and nothing in these tasks
deletes them. Changing the `ADT` storage group (lifetime, stop, delete units) loses history —
only with the user's explicit approval (skill `history-management`).
- Switching a classifier's `STORAGE` off stops recording that event type: confirm with the user.
- Setup files in `tls\sup` (`adtsys.sup`, per-process files) need admin rights: hand them to
the user (skill `portal-setup`, `change-setup-file.md`).
- Example names come from `CI-Eng-Sample` (selection group `CIENG_ITEMS`, report `CIENG_AUDIT`,
logger setup file `audit/adtlogci.sup`).
| Task | File | Status |
|---|---|---|
| Check AUDIT Service: processes, storage group `ADT`, classifier and selection group counts | `tasks/audit-checks.md` | verified |
| Read the audit trail: export, RQL query, audit report, what gets recorded by which tool | `tasks/read-audit-trail.md` | verified |
| Choose what is stored (classifier `STORAGE`), selection groups, event logger `ADTLOG` | `tasks/configure-audit.md` | verified (operator-side item value events from docs, ISS-049) |
| Distributor process, extra collectors, new classifier entities in C | L25 summary §2, §5 | from docs |

View file

@ -0,0 +1,59 @@
---
task: Check AUDIT Service (processes, storage group ADT, classifiers, selection groups)
version: R1.03
source: IM 36K10L25-01EN §1.2, §2.1.1, §2.3.1, §4.1; practiced on the test system 2026-10-01
status: verified
---
# AUDIT Service checks
All read-only.
## 1. Processes
```
tasklist /FI "IMAGENAME eq adt*"
durwfp -p adtsto -t 0 (errorlevel 0 = running)
```
Default (`tls\com\audit_start.cmd`): `adtsto.exe` (storage, process `ADTSTO`) and `adtcol.exe`
(collector `ADTCOL01`). AUDIT Service starts after HISTORY Service and refuses to start when
`his` is not running; `ADTCOL01` exits if storage group `ADT` does not exist (first start:
`ADTSTO` creates it). `adtdst` (distributor), `adtlog` (event logger) and `adtcol02` are only in
commented lines. Stop: `audit_stop.cmd` (`durstp` on `adt*`, admin).
## 2. Storage group `ADT`
```
@FIELDS
NAME,LIFE_TIME,ROLLOVER_INT,START_TIME,STOP_TIME,TYPE
@SELECT
'NAME = "ADT"'
@HIS_GROUP_DF
```
`dssqld -e adt.qlo adt.qli`. History type 6 (audit). Manual default when `ADTSTO` creates it:
rollover 1 day, unit lifetime 2 days; the test system had **52 weeks** lifetime, rollover
1 day. While storage of `ADT` is stopped, new events are refused (logged via UMH). Unit
details: skill `history-management`, `history-checks.md`.
## 3. Classifiers and selection groups
```
dssqld -e ecl.qlo -d AUDIT_EVENT_CLAS_DF
dssqld -e sgp.qlo -d AUDIT_SELGRP_DF
```
R1.03.00 test system: 463 classifiers (`BASIC_SET` 1), 444 with `STORAGE` 1. Off by default:
everything from source `COMPUTE` (PROCESS Service) on `ITEM`/`SUB-ITEM` values, status,
quality, limits and deadband, and `DATASET.NULL-ATTR.*.COMPUTE`. No selection groups exist
until you create one (the file `tls\dat\adt_sgp.dat` is created empty by `ADTSTO`).
Files: `%TLS_DAT_PATH%\adt_ecl.*` (classifiers), `adt_sgp.*` (selection groups); audit records
are in the history files of group `ADT` (`%TLS_HIS_PATH%`).
## 4. Setup files
Only `tls\sup\adtsys.sup` is installed (`QUESIZE = 200`, the rest commented): it is the keyword
reference and template. A process reads a setup file named after itself (`adtsto.sup`,
`adtcol01.sup`, `adtlog.sup` …) if present. Keywords: `configure-audit.md` §4 and the L25 summary.

View file

@ -0,0 +1,109 @@
---
task: Choose what AUDIT Service stores (classifier STORAGE, AUDIT_INFO), define selection groups, run an event logger (ADTLOG)
version: R1.03
source: IM 36K10L25-01EN §2.4, §3, §4.2, App. 1; practiced on CI-Eng-Sample 2026-10-01
status: verified (operator-side ITEM.* value events from docs, ISS-049)
---
# Configure the audit trail
## 1. Event classifiers — what is stored
Each event type is a classifier `<SUBJECT>.<ATTRIBUTE>.<ACTION>.<SOURCE>` in
`AUDIT_EVENT_CLAS_DF` (`NAME`, `SUBJECT`, `ATTRIBUTE`, `AGITATION` = action, `SOURCE`,
`BASIC_SET`, `STORAGE`). Only `STORAGE` can be changed. Configuration and DSS value changes use
subject `DATASET` with attribute `NULL-ATTR`, e.g. `DATASET.NULL-ATTR.MODIFY.LOC-ENG-MOD`
(Engineering Module) or `….ENT-ENG-MOD` (`dssqld`); logins use `CI-SERVER.NULL-ATTR.LOGIN.<source>`.
List the classifiers (and which are off): `dssqld -e ecl.qlo -d AUDIT_EVENT_CLAS_DF`. Change:
```
@FIELDS
NAME,STORAGE
@AUDIT_EVENT_CLAS_DF
"<SUBJECT>.<ATTRIBUTE>.<ACTION>.<SOURCE>",0
```
`dssqld -m`, or in the Engineering Module *Configuration › Audit trail › Event classifiers* (the change itself is audited: `AUDIT_EVENT_CLAS_DF` `STORAGE` `MODIFY`).
**Not immediate:** the processes that report events (e.g. `DSSSDA`) cache the storage flags and
re-read them every `ECL_REFRESH` seconds (default 1800). Verified: a classifier switched off was
still recorded right after the change and no longer 31 minutes later; switching it back on is
delayed the same way. Allow up to 30 minutes or restart CI Server (ISS-050). Confirm with the user before
switching anything off.
### Item option *Audit trailing wanted* (`AUDIT_INFO`)
`ITEM_DF` / `SUB_ITEM_DF` / `EXTERNAL_ALARM_DF` field `AUDIT_INFO` (default 0). It did **not**
change what the tested tools record: DSS and Engineering Module value writes are audited for all
items, `itmval -p` for none. It is meant for the `ITEM.*` / `SUB-ITEM.*` classifiers (value,
status, limits) raised by ITEM Service for operator and PROCESS writes; PROCESS (`COMPUTE`) also
needs `AUDIT = YES` in `tls\sup\opc.sup` (installed `NO`) and its classifiers are off by default.
Not verified (ISS-049).
## 2. Selection groups
A selection group is a named, compiled filter for an AUDIT destination (`ADTLOG`, the
chronological overview). Dataset `AUDIT_SELGRP_DF`: `NAME` (≤ 32), `DESCRIPTION`, `EXPRESSION`
(memo), `COMPILE` (1 = compile now), `LISTING` (compiler output), `VALID_EXPRESSION`.
Expression language (from the compiler's own listing):
- Words compared with a **string**: `aai1 acnd acnm actm mai1 nond nonm reas sacs sact satr sbgp
sbid term user` (same meaning as the `E_LAYOUT` units in §4: `sbgp` subject, `satr` attribute,
`sact` action, `sacs` source, `sbid` subject id, `user` …).
- Words compared with a constant: `nval oval` (new / old value).
- Operators `= != > < >= <=`, `and`, `or`, parentheses. **No `LIKE`**: match a name prefix with a
range, e.g. `sbid >= "<Section>." and sbid < "<Section>/"` (`/` sorts right after `.`).
Example (`examples/CI-Eng-Sample/19_audit_df.qli`):
```
@FIELDS
NAME,DESCRIPTION,EXPRESSION,COMPILE
@AUDIT_SELGRP_DF
"CIENG_ITEMS","Audit events on CI-Eng-Sample",@"
sbid >= "CI-Eng-Sample." and sbid < "CI-Eng-Sample/"
"@,1
```
`dssqld -i`. Write the memo **over several lines** (`@"` newline … newline `"@`): on one line
`@"<text>"@` is taken as a file name (`CRL-E-EINVAL` / `CRL-E-ENOENT`). Check: export the dataset
— `LISTING` ends with `ADTT-I-CMP_SUCC, Expression successfully compiled` and
`VALID_EXPRESSION` is 1. An error (e.g. `ADTT-E-UNKNOWN_TOK`) makes the `dssqld` line fail with
`ADTT-E-CMP_NO_SUCC` and leaves `VALID_EXPRESSION` 0. Remove with `dssqld -r` (`NAME` only).
## 3. Event logger `ADTLOG`
`adtlog -n <name>` connects to `ADTSTO` and prints each new event as text (stdout, or the
printer in `PRT_DEV`). It is not started by default (`audit_start.cmd` has it commented out;
`fmfprt.sup` assigns the printer function `AUDIT_TRAIL` to `ADTLOG`). A process reads
`tls\sup\<name>.sup`, so one setup file per logger instance.
Without a setup file the default layout is three lines per event (time with milliseconds,
subject, attribute, action, source / subject id, user / old and new value). Verified test:
`adtlog -n adtlogt` in a console, then a value write — the logger printed the `LOGIN`, the
`ITEM_VAL` change and the `LOGOUT`. A console logger runs until stopped: Ctrl+C, or `durstp -m -p <name>` (skill
`system-management`, `bus-utilities.md`).
Filtered logger: `examples/CI-Eng-Sample/audit/adtlogci.sup` (`SEL_GROUP = "CIENG_ITEMS"`, one-line
`E_LAYOUT`, `TIMEFMT`, `HEADER`, `HEADER_AFTER`). The user copies it to
`%TLS_ROOT_PATH%\tls\sup\` (admin); then `adtlog -n adtlogci` printed only the CI-Eng-Sample
changes (no logins), one line each under the header. If the selection group does not exist or
did not compile, the logger logs an error and exits. To run it permanently, add a
`start /B /NORMAL %TLS_ROOT_PATH%\tls\exe\adtlog -n <name>` line to `audit_start.cmd` (admin,
restart).
## 4. Setup keywords (`adtsys.sup` is the template)
`MAX_OPEN_UNITS` (20), `PRT_DEV`, `QUESIZE` (kB), `SEL_GROUP`; `COL_PROC`, `DST_PROC`, `HIS_PROC`,
`STO_PROC` = `<node>, <name>`; `NODE_ECL_FILE`, `NODE_SGP_FILE`; `E_LAYOUT = <unit>,<width>,…`
(`AAI1 ACND ACNM ACTM MAI1 NOND NONM NOTM NVAL NWLN OVAL REAS SACS SACT SATR SBGP SBID SPCE TERM
USER`), `E_NOSPACE`, `TIMEFMT` (`DD/MM/YY hh:mm:ss.ppp` default — milliseconds shown, as the
manual says); `ECL_REFRESH` (1800 s), `FLOWC` (30, 10), `HBEAT` (10), `TRYCON` (10); `FORM_FEED`,
`HEADER` (repeat for more lines), `HEADER_AFTER` (re-print after n events; the header is also
printed once at start). Which keyword applies to which process: L25 §4.2.2.
## 5. Retention
Audit records live in history storage group `ADT` (rollover 1 day; lifetime 52 weeks on the
test system). Longer/shorter retention = change `LIFE_TIME` of `ADT` (skill
`history-management`); archive like any storage group. Ask before shortening it.

View file

@ -0,0 +1,87 @@
---
task: Read the audit trail (export, RQL query, audit report) and know what each tool records
version: R1.03
source: IM 36K10L25-01EN §1.1, §2.1.2, §3.1, App. 1; IM 36K10G10-01EN ch. 9; practiced on CI-Eng-Sample 2026-10-01
status: verified
---
# Read the audit trail
Read-only. Dataset `AUDIT_TRAIL` (storage group `ADT`); every field is read-only except
`APPLICATION_SUB` (the "modifiable ASCII application info") and `PROFILE`.
## 1. Fields
| Field | Content |
|---|---|
| `NAME` | `<ACTION_TIME>/<ACTION_STAMP>`, e.g. `01-OCT-26 17:05:00.181/84` |
| `ACTION_TIME`, `NOTIFICATION_TIME`, `MODIFICATION_TIME` | When it happened / reached AUDIT Service / `APPLICATION_SUB` was last changed |
| `SUBJECT_GROUP` | Subject: the **dataset name** for configuration and DSS value changes (`ITEM_DF`, `ITEM_VAL`, `SECTION_DF`, `REPORT_DF`, `AUDIT_EVENT_CLAS_DF` …) or a classifier subject (`CI-SERVER` for logins, `ITEM`, `SUB-ITEM` …) |
| `SUBJECT_ATTRIBUTE` | Changed field (`HIGH_LIMIT`, `ITEM_VALUE`, `DESCRIPTION` …); empty for insert/delete/login |
| `SUBJECT_ACTION` | `INSERT`, `MODIFY`, `DELETE`, `LOGIN`, `LOGOUT`, `LOGIN-ATTEMPT`, `ACKNOWLEDGE`, `SHELVE`, `UN-SHELVE` |
| `SUBJECT_SOURCE` | Tool that made the change (table in §2) |
| `SUBJECT_IDENT` | Record name: item, section, object (`<object>:<attribute>` for attribute values) … |
| `USER_NAME`, `PROFILE`, `TERMINAL` | CI Server user and profile; terminal often empty |
| `ACTION_NODE`/`ACTION_PROCESS`, `NOTIFICATION_NODE`/`NOTIFICATION_PROCESS` | Node and process (`DSSSDA00`, `JHMISET1086`, `DSSQLD00875` …) |
| `OLD_VALUE`, `NEW_VALUE` | Text, max 64 characters (longer values are cut) |
| `REASON`, `APPLICATION_INFO`, `APPLICATION_SUB` | Free text from the notifying program (empty in the tests) |
## 2. What is recorded (verified on R1.03.00)
| Action | Recorded as |
|---|---|
| `dssqld` load / modify / remove (any dataset) | `<DATASET>`, field, `INSERT`/`MODIFY`/`DELETE`, source **`ENT-ENG-MOD`**, user `FULL AUTHORIZATION`, plus a `CI-SERVER` `LOGIN`/`LOGOUT` pair per `dssqld` run (not `QUICKLOAD`) |
| Writing a value through DSS (`dssqld -m` on `ITEM_VAL`) | `ITEM_VAL` `ITEM_VALUE` `MODIFY`, old and new value — for **every** item, whatever its *Audit trailing wanted* (`AUDIT_INFO`) |
| Engineering Module: change an item field | `ITEM_DF` `<FIELD>` `MODIFY`, source `LOC-ENG-MOD`, user `ADMIN` (the logged-in user) |
| Engineering Module: right-click item › *Update value* | `ITEM_VAL` `ITEM_VALUE_STR` `MODIFY` (old/new) and `ITEM_VAL` `STATUS` `MODIFY`, source `LOC-ENG-MOD` |
| Engineering Module / Operator / OPC UA server login | `CI-SERVER` `LOGIN` / `LOGOUT`, source `LOC-ENG-MOD`, `OPER-INTERFACE`, `VIA-OPC-UAS` |
| `itmval -p` (ITEM Service API) | **nothing**, even with `AUDIT_INFO` 1 |
The `ITEM.VALUE.MODIFY.*` style classifiers (subject `ITEM`) were not produced by any of these
tools; they are expected from operator displays and PROCESS Service on items with
`AUDIT_INFO` 1 (open: ISS-049). The `SUBJECT_SOURCE` of a user interface comes from its *audit
trail id* in `dssana.sup` `USER_INTERFACE` (Engineering Module = `LOC-ENG-MOD`).
## 3. Export
`dssqld -e` skips `AUDIT_TRAIL` in a full export (`NO-EXPORT` in `dssqld.sup`); name it:
```
dssqld -e audit.qlo -d AUDIT_TRAIL
```
or filter (dates as `dd-mm-yyyy hh:mm:ss`, local time):
```
@FIELDS
NAME,SUBJECT_GROUP,SUBJECT_ATTRIBUTE,SUBJECT_ACTION,SUBJECT_SOURCE,SUBJECT_IDENT,USER_NAME,OLD_VALUE,NEW_VALUE
@SELECT
'SUBJECT_IDENT = "<Section>.<Tag>" AND ACTION_TIME > "01-10-2026 17:00:00"'
@AUDIT_TRAIL
```
`dssqld -e out.csv audit.qli -c` (CSV). **Keep `NAME` in `@FIELDS`**: without the key field the
export silently returns 0 records (verified). The whole trail can be large (5 000 records after a
year of test work). Wildcards: `SUBJECT_IDENT LIKE "<Section>.*"` (`*`, not `%`; `=` with `*`
matches nothing).
## 4. RQL query and audit report
```
column t as 'DD-MM-YYYY hh:mm:ss' heading 'Time';
select action_time t, subject_group, subject_attribute, subject_action, subject_source,
subject_ident, user_name, old_value, new_value
from audit_trail
where action_time > @date - 3600 and subject_ident like '<Section>.%'
order by action_time;
```
Use aliases with `COLUMN … AS 'A12'` to keep lines short (the fields are 16–256 characters
wide). Try it in the interactive generator (skill `reporting`, `rql-interactive.md`). The sample
report `CIENG_AUDIT` (`examples/CI-Eng-Sample/19_audit_df.qli`) lists the last hour of events on
`CI-Eng-Sample.*`; generate it like any ad-hoc report (`define-reports.md` §2). Generated from
`dssqld` it is stored but not printed (`FSL-E-PRT_UNKUSER`, ISS-045).
In the Engineering Module, *Configuration › Reporting › Reports* holds the system reports
`AUDIT_TRAIL` and `UA_SERVER_AUDIT` (IM 36K10C30 App. 1). Generated there (as the logged-in
user) `CIENG_AUDIT` printed to `CIENG_FILE` and showed in the report viewer (checked by the user).

View file

@ -66,8 +66,9 @@ NAME,PARAM_VALUE_1,GENERATE
```
`dssqld -m`. `GENERATE` returns to 0 when finished (a second or two for small reports). The run is
made as user `FULL AUTHORIZATION` by `DSSQLD<pid>`; without `ADHOC_DEST` the manager then logs
`FSL-E-PRT_UNKUSER` (the report is still stored, ISS-045).
made as user `FULL AUTHORIZATION` by `DSSQLD<pid>`; the manager then logs `FSL-E-PRT_UNKUSER` and
prints nothing, even with `ADHOC_DEST` set (the report is still stored, ISS-045). To get printed
output, generate from the Engineering Module.
## 3. Read generated reports

View file

@ -0,0 +1,42 @@
@LANGUAGE
ENGLISH
@VERSION
1.03.00
! CI-Eng-Sample audit trail examples, CI Server R1.03.00. Load after 18_report_df.
! CIENG_ITEMS : AUDIT Service selection group = events on CI-Eng-Sample objects. Expressions
! have no LIKE: a name prefix is matched with >= "CI-Eng-Sample." and
! < "CI-Eng-Sample/" ('/' sorts right after '.'). COMPILE 1 compiles on load;
! the result is in LISTING and VALID_EXPRESSION.
! CIENG_AUDIT : ad-hoc report of the audit events on CI-Eng-Sample of the last hour.
@FIELDS
NAME,DESCRIPTION,EXPRESSION,COMPILE
@AUDIT_SELGRP_DF
"CIENG_ITEMS","Audit events on CI-Eng-Sample",@"
sbid >= "CI-Eng-Sample." and sbid < "CI-Eng-Sample/"
"@,1
@FIELDS
NAME,DESCRIPTION,PRIORITY,ADHOC_ENABLED,LIFE_TIME,ADHOC_DEST,QUERY
@REPORT_DF
"CIENG_AUDIT","CI-Eng-Sample audit trail, last hour",0,1,"1 Weeks","CIENG_FILE",@"
/* Who changed what on CI-Eng-Sample in the last hour */
set @width 160;
column t as 'DD-MM-YYYY hh:mm:ss' heading 'Time';
column grp as 'A12' heading 'Subject';
column attr as 'A16' heading 'Attribute';
column act as 'A8' heading 'Action';
column src as 'A12' heading 'Source';
column id as 'A32' heading 'Name';
column usr as 'A18' heading 'User';
column ov as 'A12' heading 'Old';
column nv as 'A12' heading 'New';
select action_time t, subject_group grp, subject_attribute attr, subject_action act,
subject_source src, subject_ident id, user_name usr, old_value ov, new_value nv
from audit_trail
where action_time > @date - 3600 and subject_ident like 'CI-Eng-Sample.%'
order by action_time;
"@

View file

@ -0,0 +1,19 @@
@LANGUAGE
ENGLISH
@VERSION
1.03.00
! Remove the CI-Eng-Sample audit report and selection group. Audit trail records themselves
! cannot be deleted (only whole units of storage group ADT, HISTORY Service).
@FIELDS
NAME
@REPORT_DF
"CIENG_AUDIT"
@FIELDS
NAME
@AUDIT_SELGRP_DF
"CIENG_ITEMS"

View file

@ -77,6 +77,8 @@ cmd /c "<repo>\examples\CI-Eng-Sample\remove.cmd"
| `CIENG_TANK1` | Report | Values of the `TANK1` items + last-hour statistics of one item (ad-hoc parameter chosen in an item browser, default `LEVEL`); daily 06:00 local time and ad hoc; output `CIENG_FILE`; lifetime 1 week |
| `CIENG_INFLOW_HI` | Report | Generated 5 s after `TANK1.INFLOW` rises above 400; output `CIENG_FILE` |
| `CIENG_HTML` | Report | Ad hoc; `TANK1` values as an HTML table (cursor loop) plus the logbook text |
| `CIENG_AUDIT` | Report | Ad hoc; audit trail events on `CI-Eng-Sample.*` of the last hour |
| `CIENG_ITEMS` | Audit selection group | Expression `sbid >= "CI-Eng-Sample." and sbid < "CI-Eng-Sample/"`, compiled on load |
Items created by objects (`TANK1.CALC.VOLUME`, `TANK1.JFLOW.sPerMin`) and their sections are
deleted with the objects; they are not in `02_item_df.qli`.
@ -102,9 +104,11 @@ New items start with status 13 (`NOT INIT`) until a value is written.
| `16_item_alarm_df.qli` | Switch on alarming for `TANK1.LEVEL` (loaded with `dssqld -m`) |
| `17_printer_df.tpl`, `17_printer_df.ps1` | Report file device and destination; the script fills in this system's node name and `%TLS_LST_PATH%` and writes `17_printer_df.qli` (not in the repo) |
| `18_report_df.qli` | Reports (`REPORT_DF`, RQL in the `QUERY` memo) |
| `19_audit_df.qli` | Audit selection group (`AUDIT_SELGRP_DF`) and audit report |
| `audit/adtlogci.sup` | Setup file for an extra audit event logger `ADTLOGCI` filtered on `CIENG_ITEMS` (copied to `tls\sup` by an administrator, not by `load.cmd`) |
| `83a_stop_report_df.qli` | Clears the schedule of `CIENG_TANK1` before removal (a scheduled report cannot be deleted) |
| `equipment/eqpciengslv_start.cmd`, `_stop.cmd` | Start/stop the Modbus slave mirror (copy to `tls\com`) |
| `76_`…`93_remove_*.qli` | Names to delete, in reverse order (reports and printer `83`/`84` first, alarm definitions last, `93`) |
| `76_`…`93_remove_*.qli` | Names to delete, in reverse order (audit `79`, reports and printer `83`/`84` first, alarm definitions last, `93`) |
| `load.cmd`, `remove.cmd` | Run the steps in the right order |
| `displays/CIENG_Tank.xml` | Display (HTML mode): title, number field on `TANK1.LEVEL`, alarm overview, trend of `TANK1.LEVEL`, button *Operator layout* |
| `displays/CIENG_Menu.xml` | Navigation display (200 x 700): *Tank 1*, *Current Alarm* (main frame), *Tank 1 popup* (layout `popup`) |
@ -185,7 +189,8 @@ gets its own storage group of type *Report*. Try them (skill `reporting`, task `
- Ad hoc: `REPORT_DF` `NAME,PARAM_VALUE_1,GENERATE` = `"CIENG_TANK1","CI-Eng-Sample.TANK1.INFLOW",1`
with `dssqld -m`, or in the Engineering Module *Configuration > Reporting > Reports* › right-click
› *Generate*. The output lands in `%TLS_LST_PATH%\cieng_report.txt` and in `REPORT_VAL`.
› *Generate*. The output lands in `REPORT_VAL`; runs from the Engineering Module also print to
`%TLS_LST_PATH%\cieng_report.txt` (runs from `dssqld` do not print, ISS-045).
- Trigger: `itmval -p -n CI-Eng-Sample.TANK1.INFLOW -v 450` → `CIENG_INFLOW_HI` 5 s later; write a
value below 400 before the next test.
- `CIENG_TANK1` also runs every day at 06:00 (local time).
@ -193,6 +198,22 @@ gets its own storage group of type *Report*. Try them (skill `reporting`, task `
`remove.cmd` clears the schedule, removes the reports (with their generated reports and logbook
files), the destination and device, and deletes `cieng_report.txt`.
## Audit trail
No admin rights needed for `19_audit_df.qli`. Every change made by `load.cmd`, `dssqld` or the
Engineering Module is in the audit trail (skill `audit-trail`):
- Generate `CIENG_AUDIT` (ad hoc, like the other reports) to list the last hour of changes on
`CI-Eng-Sample.*`: time, dataset, field, action, source, user, old and new value.
- Export: `dssqld -e audit.qlo -d AUDIT_TRAIL` (whole trail) or a qli with `@SELECT` (keep `NAME`
in `@FIELDS`).
- Event logger (optional, admin): copy `audit\adtlogci.sup` to `%TLS_ROOT_PATH%\tls\sup\`, then
run `adtlog -n adtlogci` in a console; it prints each new CI-Eng-Sample event on one line
(Ctrl+C to stop). Delete the file from `tls\sup` when the sample is removed.
Audit records themselves cannot be deleted; `remove.cmd` removes only the report and the
selection group.
## Planned additions
| Phase | Adds |

View file

@ -0,0 +1,11 @@
! CI-Eng-Sample: setup file for an extra AUDIT Service event logger (ADTLOG) named ADTLOGCI.
! A setup file is named after the process; copy this file to %TLS_ROOT_PATH%\tls\sup (admin)
! and start the logger with: adtlog -n adtlogci
! It prints only events of selection group CIENG_ITEMS (load 19_audit_df.qli first; the
! group must have compiled, else the logger exits). Output goes to stdout (no PRT_DEV).
! Keywords: see adtsys.sup (template) and knowledge/manuals/IM36K10L25-01EN.md.
SEL_GROUP = "CIENG_ITEMS"
TIMEFMT = "DD-MM-YYYY hh:mm:ss"
E_LAYOUT = ACTM,19,SBGP,12,SATR,14,SACT,8,SACS,12,SBID,32,USER,18,OVAL,12,NVAL,12
HEADER = "Time Subject Attribute Action Source Name User Old New"
HEADER_AFTER = 20

View file

@ -42,3 +42,5 @@ rem from 17_printer_df.tpl), then the report definitions.
powershell -NoProfile -ExecutionPolicy Bypass -File 17_printer_df.ps1
dssqld -i 17_printer_df.qli -l 17_printer_df.qlo
dssqld -i 18_report_df.qli -l 18_report_df.qlo
rem Audit trail: selection group (compiled on load) and an ad-hoc audit report.
dssqld -i 19_audit_df.qli -l 19_audit_df.qlo

View file

@ -1,10 +1,11 @@
@echo off
rem Remove CI-Eng-Sample from a CI Server R1.03 TEST system (also deletes its history).
rem Run in an elevated prompt while CI Server is running; call this script by full path.
rem Order: reports, printer, OPC UA, Modbus, auth group, object, class, trigger group, storage links, stop + delete storage groups, items, sections (children first).
rem Order: audit report + selection group, reports, printer, OPC UA, Modbus, auth group, object, class, trigger group, storage links, stop + delete storage groups, items, sections (children first).
rem A storage group with an active unit cannot be deleted (HIS-E-GROUPHASUNT), so the
rem group first gets a stop time one minute ahead; the script waits until it has passed.
cd /d "%~dp0"
dssqld -r 79_remove_audit_df.qli -l 79_remove_audit_df.qlo
rem Reports first (they refer to TANK1.INFLOW and the destination), then destination and device.
rem A scheduled report cannot be deleted, so its schedule is cleared first.
dssqld -m 83a_stop_report_df.qli -l 83a_stop_report_df.qlo

View file

@ -64,7 +64,10 @@ development system (see "Test system" in `progress.md`); they do not exist on ot
| ISS-042 | 2026-10-01 | GRAPHICS (layouts) | Installed vs `Layouts.readme`: the factory layouts use status line item types `displayName`, `playbackIndicator` and `dateTime` and the commands `reload <frame>` / `reload all`, none of which the readme lists (readme: `statusText`, `userName`, `progresBar`, `graphicsQueueLevel`, `connectionState`); the readme also writes `zooom` for the zoom command (factory files use `zoom`). | open | Installed software is the reference (standing user decision). Close when the user confirms. | `.claude/skills/graphics/tasks/layouts.md` §2 |
| ISS-043 | 2026-10-01 | REPORT (system reports) | IM 36K10C30 App. 1.3 names two system reports `ALM_ATTS_CUR` and `ALM_ATRS_HIS`; the installed reports are `ALM_ATTRS_CUR` and `ALM_ATTRS_HIS`. The other 26 names match. | open | Installed software is the reference (standing user decision). Close when the user confirms. | `knowledge/manuals/IM36K10C30-01EN.md` §8 (done) |
| ISS-044 | 2026-10-01 | REPORT (scheduling) | Behaviour not in the manuals, found by quick load: a generation interval below 10 minutes is refused (`HIS-E-ROLLTOFAST`, the interval is the rollover of the report's storage group); a scheduled report cannot be deleted (`RPT-E-ACTIVE`) until `ACTIVATION_TIME` and `GENERATION_INTERVAL` are cleared; `CORRECT_DAYLIGHT` 0 counts intervals in UTC (06:00 set for January ran at 05:00 in October); a past activation time moves to the next slot - once (modify, past time within the lifetime) a single report labelled with the old time was generated, at insert with an older time none. | open | Documented as verified behaviour; the one-off generation for a past activation time is not fully understood. Close when the user confirms. | `.claude/skills/reporting/tasks/define-reports.md` §1, §5, §6; `knowledge/manuals/IM36K10C30-01EN.md` §2; `examples/CI-Eng-Sample/83a_stop_report_df.qli`, `18_report_df.qli` |
| ISS-045 | 2026-10-01 | REPORT (ad hoc from `dssqld`) | Generating ad hoc with `REPORT_DF.GENERATE` = 1 from `dssqld` (user `FULL AUTHORIZATION`) on a report without `ADHOC_DEST` logs `FSL-E-PRT_UNKUSER, Job submitted by unknown user (FULL AUTHORIZATION)` and `RPT-I-TRYPRINT` in `umhlog.log`; the generated report is stored normally. With `ADHOC_DEST` set no error appears and the device gets the output. Related to the R1.03 known issue on report generation and default printers (IM 36K01A50, REPORT 1.11). | open | Workaround documented (set `ADHOC_DEST`). 2026-10-01: generating from the Engineering Module as user `ADMIN` with destination `CIENG_FILE` printed without errors, so it only affects runs from `dssqld`. Close when the user confirms. | `.claude/skills/reporting/tasks/define-reports.md` §2; `knowledge/manuals/IM36K10C30-01EN.md` §6 |
| ISS-045 | 2026-10-01 | REPORT (ad hoc from `dssqld`) | Generating ad hoc with `REPORT_DF.GENERATE` = 1 from `dssqld` (user `FULL AUTHORIZATION`) on a report without `ADHOC_DEST` logs `FSL-E-PRT_UNKUSER, Job submitted by unknown user (FULL AUTHORIZATION)` and `RPT-I-TRYPRINT` in `umhlog.log`; the generated report is stored normally. Phase 12 correction (2026-10-01): with `ADHOC_DEST` set the same error appears and nothing is printed (`CIENG_AUDIT`, `CIENG_TANK1` after a sample reload); the same report generated from the Engineering Module as `ADMIN` printed to `CIENG_FILE`. Related to the R1.03 known issue on report generation and default printers (IM 36K01A50, REPORT 1.11). | open | Workaround documented (set `ADHOC_DEST`). 2026-10-01: generating from the Engineering Module as user `ADMIN` with destination `CIENG_FILE` printed without errors, so it only affects runs from `dssqld`. Close when the user confirms. | `.claude/skills/reporting/tasks/define-reports.md` §2; `knowledge/manuals/IM36K10C30-01EN.md` §6 |
| ISS-046 | 2026-10-01 | DATABASE (`dssqld` memo) | A memo field loaded from a file (`@"<file>"@`, IM 36K10L50 §3.10) fails with a relative name (`CRL-E-ENOENT`, the file is read on the server side) and with a long absolute path (`DSSG-E-STRBUFSMAL`, buffer 83); a short absolute path works. The manual gives no limits. | open | Documented: use inline memos, or an absolute path ≤ 82 characters. Close when the user confirms. | `.claude/skills/system-management/tasks/dss-tools.md` §2; `knowledge/manuals/IM36K10L50-01EN.md` §4 |
| ISS-047 | 2026-10-01 | REPORT (RQL manuals) | The manuals disagree: default `@WORKSPACE` 500 KB (IM 36K10R40 §2.2.2) vs 16 KB (IM 36K10C30 table 2.1-1, IM 36K10P20 §9.6); maximum `@WIDTH` 512 (R40, P20 §4) vs 5000 (P20 §9.6); `@FORMFEED` described with opposite meanings (C30: not 1 = form feed; P20: 0 = blank lines, default 1). Installed set-up files set `@workspace` explicitly (500 in `rptge1.rpt`, 100 in `rptgen.rpt`) and `@formfeed 0` for the interactive generator. | open | Not tested (no printer); the set-up files make the defaults irrelevant in practice. | `knowledge/manuals/IM36K10R40-01EN.md` §2; `knowledge/manuals/IM36K10P20-01EN.md` §3 |
| ISS-048 | 2026-10-01 | REPORT (ad-hoc parameters) | The prompt `[ITEM:NAME like "CI-Eng-Sample.TANK1.*"]Item for statistics:` (filter form as in IM 36K10C30 §2.1) gives an item tree browser in the Engineering Module generate dialog, but the tree shows all sections, not only `TANK1` items (checked by the user). | open | Try other filter forms (`%` wildcard, `SECTION = …`, `[ITEM:TAG="…"]`) and the display report component. | `.claude/skills/reporting/tasks/define-reports.md`; `knowledge/manuals/IM36K10C30-01EN.md` §2; `examples/CI-Eng-Sample/18_report_df.qli` comment |
| ISS-049 | 2026-10-01 | AUDIT (item option *Audit trailing wanted*) | IM 36K10G10 ch. 9 and the classifier list (IM 36K10L25 App. 1, `ITEM.VALUE.MODIFY.<source>`, `ITEM.HIGH-LIMIT…`) suggest item changes are audited per item when `AUDIT_INFO` = 1. On R1.03.00 none of the tested tools produced an `ITEM.*` event: `itmval -p` writes are not audited at all (with `AUDIT_INFO` 0 or 1); value writes through DSS (`dssqld -m ITEM_VAL`) and Engineering Module *Update value* are audited as dataset events (`ITEM_VAL`, `ITEM_VALUE` / `ITEM_VALUE_STR` / `STATUS`) for every item regardless of `AUDIT_INFO`. Operator-display writes and PROCESS writes (`opc.sup` `AUDIT = YES`, `COMPUTE` classifiers off by default) were not tested (no input field in the sample displays). | open | Test an operator value input on an item with `AUDIT_INFO` 1 (needs a display with an input field) and, if wanted, PROCESS with `AUDIT = YES`. | `.claude/skills/audit-trail/tasks/configure-audit.md` §1; `.claude/skills/audit-trail/tasks/read-audit-trail.md` §2; `knowledge/manuals/IM36K10L25-01EN.md` §3 |
| ISS-050 | 2026-10-01 | AUDIT (classifier `STORAGE`) | Setting `AUDIT_EVENT_CLAS_DF.STORAGE` = 0 for `DATASET.NULL-ATTR.MODIFY.ENT-ENG-MOD` at 17:01:12 did not stop the next `dssqld -m ITEM_VAL` change from being stored (17:01:12.573). IM 36K10L25 §3.2 explains a per-process cache refreshed every `ECL_REFRESH` s (default 1800); the notifier here is `DSSSDA`, so the change should apply within 30 minutes. | open | Re-tested: at 17:32:18 (after the 30-minute refresh) the same change was **not** stored, so the flag works with a delay. Set back to 1 at 17:32; the next change was still not stored (the cache works in both directions). Documented: allow up to `ECL_REFRESH` (1800 s) or restart CI Server. Close when the user confirms. | `.claude/skills/audit-trail/tasks/configure-audit.md` §1; `knowledge/manuals/IM36K10L25-01EN.md` §3 |
| ISS-051 | 2026-10-01 | AUDIT (manual vs installed) | Differences between IM 36K10L25 and R1.03.00: (1) App. 1 lists subject `F/T-SYSTEM`, the installed classifiers use `CI-SERVER` (logins) and also `EAL OPERATION` (subject and action) and source `VIA-OPC-UAS`, not in the manual; 463 classifiers installed. (2) App. 1 explanations of `SHELVE` and `UN-SHELVE` are swapped. (3) `QUESIZE`: manual default and maximum 200 kB, `adtsys.sup` help default 10 kB, minimum 10 (file sets 200). (4) `TIMEFMT` default: manual `DD/MM/YY hh:mm:ss.ppp`, `adtsys.sup` help without `.ppp`; `ADTLOG` output shows milliseconds (manual right). (5) `dssqld` changes are recorded with source `ENT-ENG-MOD`, not `QUICKLOAD`. (6) The selection expression language is not described in the manual; the compiler listing gives the words and operators (no `LIKE`). (7) `ADT` group lifetime 52 weeks on the test system vs 2 days default when `ADTSTO` creates it (§2.1.1). | open | Documented in the L25 summary and the `audit-trail` skill. Close when the user confirms. | `knowledge/manuals/IM36K10L25-01EN.md`; `.claude/skills/audit-trail/tasks/*.md` |

View file

@ -112,9 +112,9 @@ Logbook on a display needs *Logbook Enabled* and *Visible* in the report. Not pr
`dssqld -r` (needs `REPORT_DELETE_GENERATED_REPORT`; users only delete their own ad-hoc ones).
- `rptgen -s rptgen.rpt` for trying RQL (`IM36K10R40-01EN.md` §6).
**Verified:** ad-hoc runs from `dssqld` are made by user `FULL AUTHORIZATION`; without an ad-hoc
destination `RPTMAN` then logs `FSL-E-PRT_UNKUSER, Job submitted by unknown user` (the report is
still stored; ISS-045). With `ADHOC_DEST` set the output went to the device without errors.
**Verified:** ad-hoc runs from `dssqld` are made by user `FULL AUTHORIZATION`; `RPTMAN` then logs
`FSL-E-PRT_UNKUSER, Job submitted by unknown user` and prints nothing, with or without
`ADHOC_DEST` (the report is still stored; ISS-045, corrected in phase 12).
Scheduled and triggered runs are made by `RPTMAN` and print to `DEST_NAME`. Generated from the
Engineering Module the run is made by the logged-in user (`ADMIN`, process `JHMISET…`) and printed
to the chosen destination without errors; *View* lists generated reports by local time and has a

View file

@ -88,7 +88,9 @@ on a schedule, or on an item event (with delay). Destinations: `DEFAULT`, `PRINT
**Audit trail (ch. 9)**: stored in dataset `AUDIT_TRAIL`, storage group `ADT`; events are
named `<subject group>.<attribute>.<action>.<source>`, e.g. `ITEM.VALUE.MODIFY.HMI`; records
cannot be deleted except by deleting storage units.
cannot be deleted except by deleting storage units. On R1.03.00 configuration and DSS changes
are recorded per dataset (e.g. `ITEM_DF.HIGH_LIMIT.MODIFY`); details in `IM36K10L25-01EN.md`,
skill `audit-trail`.
**RDBMS exposure (ch. 10)**: copies CI Server data (`ITEM_VALUES` aggregated per interval,
`ITEM_HISTORY` with a mandatory filter, `ITEM_INPUTS` for writes back, or any dataset on

View file

@ -0,0 +1,144 @@
---
manual: IM 36K10L25-01EN
title: Audit Trail Management Engineering
edition: 3rd Edition, Sep. 2023
version: R1.03
status: processes, scripts, adtsys.sup, classifiers, ADT group, AUDIT_TRAIL contents, selection groups and ADTLOG (default and filtered) verified on the test system 2026-10-01; distributor, extra collectors, classifier extension in C and operator-side ITEM.* events from docs
---
# Audit Trail Management Engineering (R1.03)
AUDIT Service records who changed what and when: value and limit changes, definition inserts /
modifies / deletes, alarm acknowledgements, logins and logouts. Events are stored in the history
storage group `ADT` and read through dataset `AUDIT_TRAIL`. The manual is written for system
integrators (processes, setup file, extending the classifier tables in C). Section numbers refer
to the manual; "installed" means checked on the R1.03.00 test system.
## 1. Interfaces and data stores (§1)
| Interface / store | Use |
|---|---|
| Notification | Applications report an event (routine `adt_evt_not`); only one field of a stored event, the *modifiable ASCII application info*, can be changed afterwards |
| Distribution | Connected processes (AUDIT destinations) receive events as they are stored, optionally filtered by a selection group |
| Retrieval | Reading stored events (collector process; `AUDIT_TRAIL` dataset) |
| History management | Storage group `ADT` is managed by HISTORY Service (rollover, lifetime, units) |
| Event classifier file | Which event types exist and whether each is **stored** — dataset `AUDIT_EVENT_CLAS_DF` (`tls\dat\adt_ecl.dat`) |
| Selection group file | Named, compiled selection expressions — dataset `AUDIT_SELGRP_DF` (`tls\dat\adt_sgp.dat`) |
Single events cannot be deleted; only whole storage units or the whole group (HISTORY Service).
## 2. Processes (§1.2, §2, §4.1)
| Process | Job |
|---|---|
| `ADTSTO` (storage) | Creates group `ADT` if missing (rollover 1 day, unit lifetime 2 days), fills the classifier file with the basic set (existing entries kept), creates the selection group file, stores events, sends them to destinations. Ignores events while storage of `ADT` is stopped. Must run on the node of the history manager `HIS` |
| `ADTCOL01` (+ `ADTCOL02`…) | Answers retrieval requests, also while storage is stopped; extra images share the queue `adtcol01` (load sharing). Exits if group `ADT` does not exist, so `ADTSTO` must start first |
| `ADTDST` (distributor) | Optional relay on another node when several destinations there want events (3 + N instead of 3 × N BUS messages) |
| `ADTLOG` (logging) | Optional destination that prints events as text (stdout or `PRT_DEV`), optionally only a selection group |
Gaps are signalled with *missing events* records/messages (storage queue overflow, lost
connection, unexpected sequence number). Destinations check sequence numbers and periodic
flow-control messages; a missing flow-control message makes them reconnect.
**Installed:** `tls\com\audit_start.cmd` does nothing if `adtsto` already runs, refuses to start
when `his` is not running, then starts `adtsto -n adtsto` and `adtcol -n adtcol01`. `adtcol02`,
`adtlog` and `adtdst` are present as commented-out lines. `audit_stop.cmd` stops `adt*` with
`durstp`. Executables in `tls\exe`: `adtsto`, `adtcol`, `adtdst`, `adtlog`, `adtimport`
(undocumented), `adtxdb` (service debugger, not documented).
## 3. Event classifiers (§3.1, Appendix 1)
An event classifier is four names `<SUBJECT>.<ATTRIBUTE>.<ACTION>.<SOURCE>`, e.g.
`ITEM.VALUE.MODIFY.HMI`. Each name has an internal code; stored events keep only the codes, so
codes must never change once used.
- **Subjects**: ALN-DEST, ALN-USR, CLASS, CLASS-ATTR, DATASET, EQUIPMENT, F/T-SYSTEM,
INSTALLATION, ITEM, OBJECT, OBJECT-ATTR, SECTION, STATION, SUB-ITEM, TRIGGER-GROUP, UNIT,
USER-PROFILE, ACKNOWLEDGE-TYP.
- **Attributes** (about 170): item properties (VALUE, STATUS, HIGH-LIMIT, LOW-LIMIT, DESCRIPTION,
ENGINERING-UNIT, ALARM-INHIBIT, ALARM-SHELVE, ENABLE-AUDIT-TR …), point/line properties,
alarm notification users and schedules, NULL-ATTR (no attribute).
- **Actions**: ACKNOWLEDGE, DELETE, INSERT, LOGIN, LOGIN-ATTEMPT, LOGOUT, MODIFY, SHELVE,
UN-SHELVE (the manual's explanations of SHELVE and UN-SHELVE are swapped).
- **Sources**: COMPUTE (PROCESS Service), DSS-CLIENT, ENT-EDIT-MOD, ENT-ENG-MOD, ENT-QUALIZATION,
FTEXCHANGE, HMI (Engineering Module), LOC-EDIT-MOD, LOC-ENG-MOD, ODBC, OPC-DA-SERVER,
OPER-INTERFACE, OTHERS, QUICKLOAD.
The notifying routine checks a cached copy of the classifier's **storage** flag and sends
nothing when storage is off; the cache refreshes every `ECL_REFRESH` seconds (default 1800), so
a change to the storage flag may take up to 30 minutes to reach running programs.
**Installed:** `AUDIT_EVENT_CLAS_DF` fields `NAME` (the four names joined), `SUBJECT`,
`ATTRIBUTE`, `AGITATION` (= action), `SOURCE`, `DESCRIPTION`, `BASIC_SET`, `STORAGE` (the only
changeable field); 463 classifiers, 444 stored. Off by default: the `COMPUTE` (PROCESS) source for
item/sub-item values, status, quality, limits, deadband, and `DATASET.NULL-ATTR.*.COMPUTE`. Not in
the manual: subject `CI-SERVER` (logins; the manual's `F/T-SYSTEM` is the old name), subject/action
`EAL OPERATION`, source `VIA-OPC-UAS` (ISS-051).
**What is actually recorded (verified):** configuration changes and DSS value writes are stored
as *dataset* events — `SUBJECT_GROUP` = dataset name (`ITEM_DF`, `ITEM_VAL`, `SECTION_DF` …),
`SUBJECT_ATTRIBUTE` = field, old and new value, user and source: `ENT-ENG-MOD` for `dssqld`
(not `QUICKLOAD`), `LOC-ENG-MOD` for the Engineering Module; every `dssqld` run also adds a
`CI-SERVER` `LOGIN`/`LOGOUT` pair. `itmval -p` writes are not audited. The item option
`AUDIT_INFO` (*Audit trailing wanted*, default 0; also on `SUB_ITEM_DF`, `EXTERNAL_ALARM_DF`) made
no difference for these tools; it is meant for the `ITEM.*` classifiers from operator/PROCESS
writes (not tested, ISS-049). A changed `STORAGE` flag takes effect only after the notifying process
re-reads it (`ECL_REFRESH`, up to 30 minutes, both directions; verified, ISS-050).
## 4. Setup files (§4.2)
Only `tls\sup\adtsys.sup` is installed; it documents every keyword and is the template for
per-process files named after the process (`adtsto.sup`, `adtcol01.sup`, `adtdst.sup`,
`adtlog.sup`, `adtovv.sup` for the chronological overview). Without a file, defaults apply.
| Tab / keyword | Meaning | Default |
|---|---|---|
| General `MAX_OPEN_UNITS` | Storage units open at once (2–100) | 20 |
| `PRT_DEV` | Printer for `ADTLOG` | stdout |
| `QUESIZE` | BUS queue size, kB | see below |
| `SEL_GROUP` | Selection group applied by the process | none |
| Node Numbers `COL_PROC`, `DST_PROC`, `HIS_PROC`, `STO_PROC` | `<node>, <name>` of collector, distributor, history manager, storage | local `ADTCOL01`, local `ADTSTO`, local `HIS`, `ADTSTO` on the host node |
| `NODE_ECL_FILE`, `NODE_SGP_FILE` | Node holding the classifier / selection group file | storage node |
| Layout `E_LAYOUT` | Message units and widths for the overview / log (`ACTM` time, `SBGP` subject, `SATR`, `SACT`, `SACS`, `SBID` subject id, `USER`, `TERM`, `OVAL`/`NVAL` old/new value, `REAS`, `AAI1`/`MAI1` application info, `ACND`/`ACNM`/`NOND`/`NONM`/`NOTM` node, program and notification time, `SPCE n`, `NWLN n`) | `SPCE,2,ACTM,21,SBGP,13,SATR,13,SACT,11,SACS,15,NWLN,1,SPCE,4,SBID,40,USER,16,NWLN,1,SPCE,6,OVAL,35,NVAL,35,NWLN,1` |
| `E_NOSPACE` | No automatic space between units | off |
| `TIMEFMT` | Picture for `ACTM` (`YYYY MMM DD hh mm ss ppp`) | see below |
| Events `ECL_REFRESH` | Classifier cache refresh, s | 1800 |
| `FLOWC` | Flow-control interval, timeout (s) | 30, 10 |
| `HBEAT` | Heartbeat, s | 10 |
| `TRYCON` | Reconnect interval, s | 10 |
| Header `FORM_FEED`, `HEADER` (repeatable), `HEADER_AFTER` | Log header | off / layout header / never repeated |
**Installed differences:** the `adtsys.sup` help says `QUESIZE` default 10 kB (minimum 10), the
manual says default and maximum 200 kB; the file sets `QUESIZE = 200`. The `TIMEFMT` default is
`DD/MM/YY hh:mm:ss` in the file help and `DD/MM/YY hh:mm:ss.ppp` in the manual; `ADTLOG` prints
milliseconds, so the manual is right (ISS-051). Also installed: `adtini.sup` (licence value only),
and `fmfprt.sup` assigns the printer function `AUDIT_TRAIL` to `ADTLOG`.
**Verified:** `adtlog -n <name>` run from a console prints new events with the default layout;
with a setup file `<name>.sup` holding `SEL_GROUP`, `E_LAYOUT`, `TIMEFMT`, `HEADER`,
`HEADER_AFTER` it printed only the selected events in the custom layout (sample
`examples/CI-Eng-Sample/audit/adtlogci.sup`).
## 4a. Selection groups (not described in the manual)
`AUDIT_SELGRP_DF`: `NAME`, `DESCRIPTION`, `EXPRESSION` (memo), `COMPILE`, `LISTING`,
`VALID_EXPRESSION`. The compiler listing names the language: string comparisons on `aai1 acnd
acnm actm mai1 nond nonm reas sacs sact satr sbgp sbid term user`, constant comparisons on `nval
oval`, operators `= != > < >= <=`, `and`, `or`, parentheses; no `LIKE` (prefix match with a range
`>= "X." and < "X/"`). Errors: `ADTT-E-UNKNOWN_TOK`, `ADTT-E-CMP_NO_SUCC`. Verified.
## 4b. Reading the trail
`AUDIT_TRAIL` (key `NAME` = `<action time>/<stamp>`; all fields read-only except `PROFILE` and
`APPLICATION_SUB`) is in `dssqld.sup` `NO-EXPORT`: export with `-d AUDIT_TRAIL` or a qli that
names it — the qli export returns 0 records unless `NAME` is in `@FIELDS`; `@SELECT` accepts
`LIKE "X.*"`. RQL `select … from audit_trail` works in reports (sample `CIENG_AUDIT`). `ADT`
group on the test system: lifetime 52 weeks, rollover 1 day. Task files: skill `audit-trail`.
## 5. Extending classifiers (§4.3)
New subjects/attributes/actions/sources are added in C: `#define` codes ≥ `0x80000000` in
`adt_ece.h`, names starting with `_`, rebuild `adt_ece()` (`tls\src\adt_ece.c`) and re-link AUDIT,
INTEGRATION, DATABASE Service and every program that uses it. **Installed:** `adt_ece.c`,
`tls\inc\adt_ece.h`, `audit_compile.cmd`/`.mak`, `audit_build.cmd`/`.mak` are shipped. System
integrator work; not practiced.

View file

@ -62,7 +62,7 @@ AID is not needed.
| 11 | IM 36K10R40 | Report Server Setup | done for processes, set-up files, interactive generator, `rptstp`; extra generators, separate RPI servers, custom destinations from docs ([notes](manuals/IM36K10R40-01EN.md)) |
| 11 | IM 36K10C30 | Engineering Module - Reporting | done by quick load for report definitions (ad hoc + parameters, schedule, item trigger, HTML, logbook), generated reports and a file device/destination; Engineering Module forms, generate and view checked by the user; report component in displays and hardcopy printers from docs ([notes](manuals/IM36K10C30-01EN.md)) |
| 11 | IM 36K10E10 | Excel Add-in | summarized, from docs (Excel not installed on the test system) ([notes](manuals/IM36K10E10-01EN.md)) |
| 12 | IM 36K10L25 | Audit Trail Management | not started |
| 12 | IM 36K10L25 | Audit Trail Management | done for processes, classifiers, `AUDIT_TRAIL` reading/export, audit report, selection groups, `ADTLOG` (default and filtered); distributor, extra collectors, classifier extension in C and operator-side `ITEM.*` events from docs ([notes](manuals/IM36K10L25-01EN.md)); skill `audit-trail` |
| 13 | IM 36K10J20 | High Availability Computing | not started (needs two servers) |
| 13 | IM 36K10J40 | Active Directory Integration | not started (needs a domain) |
| — | IM 36K01A10 / A20 / A30 | Read Me First, License, OSS terms | skipped (no engineering content) |
@ -109,7 +109,7 @@ now come before classes and objects (phase 6), and the other interfaces follow a
| C10 | Integrator time unit: integration granule `itm_int_secs` in `itm.sup` ([task](../.claude/skills/item-engineering/tasks/sub-items.md)) | passed | passed | 60 → `RUN_SECONDS` +1 per minute; restored to 1 (file identical to backup), +1 per second again ([ISS-010](issues.md)). Elevated restarts run by the user. |
| G10 | Displays, symbols, Operator Interface test | display done (phase 10); symbols not practiced | display added | Display `CIENG_Tank` built in the Edit Module and checked in the HTML display. |
| L41/C10 | Modbus TCP line, station, scan type, points, connected items by quick load ([task](../.claude/skills/equipment/tasks/modbus-station.md)) | passed | passed | Loopback to CI Server's own Modbus slave (`eqpmdcmem` + `eqpmdcslvtcp` on 5020, started by hand). Line load created and started `EQPCIENG`; removal stopped it and deleted its files. Write/read-back, off-scan/on-scan checked; full remove/reload from sample files. Protocol must be Open Modbus/TCP ([ISS-024](issues.md)). Mirror start files copied to `tls\com` by the user; after a restart everything came back under the CI Service and the setpoint was re-sent on connect. |
| G10 | Alarms, reports, audit, RDBMS, history | alarms (phase 8), history (phase 9), reports (phase 11) done; audit, RDBMS not practiced | alarms, history, reports added | Covered in their own phases (7–12). |
| G10 | Alarms, reports, audit, RDBMS, history | alarms (phase 8), history (phase 9), reports (phase 11), audit (phase 12) done; RDBMS not practiced | alarms, history, reports, audit added | Covered in their own phases (7–12). |
| R10/R20 | Read a setup file: active settings and keyword help ([task](../.claude/skills/portal-setup/tasks/read-setup-file.md)) | passed | n/a | Read-only. Compared with the Setup File Editor GUI for `wfla_display.sup`, `wflgdi.sup` and all 9 tabs of `jwuiisg.sup`: fields and values identical. Manual differences logged as ISS-012 to ISS-017 (installed software taken as the reference). |
| R10 | Check web access for CI View: ports, Remote Connect page, `DEPLOY` folder ([task](../.claude/skills/portal-setup/tasks/check-web-access.md)) | passed | n/a | 8080/8443 listening, page 200, six `DEPLOY` folders. |
| R10/R20 | Change a setup file safely ([task](../.claude/skills/portal-setup/tasks/change-setup-file.md)) | passed | n/a | `jwuiisg.sup` HTTP port 8080 → 8081 (text edit, elevated restart): 8081 served the page, 8080 refused; restored, hash identical to backup. Editor: *OK* writes at once, *Reset Field* restores the default (ISS-016). |
@ -142,3 +142,6 @@ now come before classes and objects (phase 6), and the other interfaces follow a
| L50/P30 | DSS tools: processes, `dss.sup`, quick load macro/include/memo file, `dssutl` read, DSS compiler syntax check ([task](../.claude/skills/system-management/tasks/dss-tools.md)) | passed | n/a | Memo from file: absolute path ≤ 82 characters only (ISS-046). Dictionary untouched. |
| C30 | Report component on a display, hardcopy printer, extra report generators | not practiced | n/a | GUI / no printer / admin restart. |
| E10 | Excel Add-in (DART) | not practiced | n/a | Excel not installed on the test system. |
| L25 | AUDIT Service checks: processes, `ADT` group, classifiers, selection groups ([task](../.claude/skills/audit-trail/tasks/audit-checks.md)) | passed | n/a | `adtsto` + `adtcol`; 463 classifiers, 444 stored; `ADT` lifetime 52 weeks; manual differences ISS-051. |
| L25 | Read the audit trail: export, RQL, audit report, what each tool records ([task](../.claude/skills/audit-trail/tasks/read-audit-trail.md)) | passed | passed | Report `CIENG_AUDIT` (`19_audit_df.qli`); qli export needs `NAME` in `@FIELDS`; `dssqld` = `ENT-ENG-MOD`, Engineering Module = `LOC-ENG-MOD` (checked by the user); `itmval` not audited (ISS-049). |
| L25 | Classifier `STORAGE`, selection groups, event logger `ADTLOG` ([task](../.claude/skills/audit-trail/tasks/configure-audit.md)) | passed | passed | Selection group `CIENG_ITEMS` compiles on load; `adtlog -n adtlogci` with sample setup file printed only CI-Eng-Sample events; storage flag cached (ISS-050); `AUDIT_INFO` effect not shown (ISS-049). Full sample remove/reload 0 errors. |