Baseline: docker stack, provisioning tools, test-data, gateway-as-files (pre-PrimeBAT build)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 11:56:30 -05:00
commit 310b1b3b9e
951 changed files with 17028 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
# Gateway API token (mint with: python3 tools/provision.py mint-token)
.env
# MariaDB password read by the 'local' file secret provider (written by provision.py)
ignition/gateway/config/secrets/
# Fresh-reset rollback copy
ignition/gateway.bak/
# Gateway-maintained content-addressed caches + probe output (never author/commit)
ignition/gateway/**/.resources/
ignition/gateway/projects/.probe/
__pycache__/
.pytest_cache/

154
README.md Normal file
View File

@@ -0,0 +1,154 @@
# Build-a-Thon — Alarm Analysis Dashboard (Ignition 8.3.7 + Perspective)
Local development environment for the Inductive Automation Build-a-Thon. Native Ignition
features only — **no third-party modules** (contest rule).
## Quickstart
```bash
docker compose up -d
```
- Gateway: <http://localhost:8088> — login `admin` / `password`
- MariaDB: `localhost:3306` — db `ignition`, user `ignition` / `ignition` (root password: `password`)
First start takes a minute or two while the gateway commissions itself (EULA, edition, and
admin credentials are seeded by env vars, so there is no commissioning wizard). Watch with:
```bash
docker compose logs -f ignition
```
The gateway is ready when `curl http://localhost:8088/StatusPing` returns `{"state":"RUNNING"}`.
## Gateway state lives in this repo (gateway-as-files)
The gateway's durable state is bind-mounted from the repo (primebench/TestingPlatform
pattern) — a container recreate can never wipe it, and the gateway never re-commissions:
| Repo path | In container (`data/`) | What's in it |
| ------------------------------------------------ | ----------------------- | ----------------------------------------------- |
| `ignition/gateway/commission/commissioning.json` | `commissioning.json` | Commissioning marker (committed) |
| `ignition/gateway/config/` | `config/` | All config resources: DB connection, journal, API token, **tags**, secrets |
| `ignition/gateway/projects/` | `projects/` | Project files: Perspective views, scripts, timers |
Everything else (internal db, logs, certs) stays ephemeral in the container. The gateway
runs as your host uid/gid (`IGNITION_UID`/`IGNITION_GID`, default 1000), so files stay
owned by you.
**Edit-files workflow:** change files under `ignition/gateway/`, then tell the gateway to
reload — `python3 tools/provision.py scan-config` (config/tags) or `scan-projects`
(project resources). Changes made in the Designer/gateway UI land back in these files,
ready to diff.
## Automated provisioning (REST API)
Gateway config is provisioned through the Ignition 8.3 HTTP API using [tools/provision.py](tools/provision.py)
(stdlib only, no pip installs). On a fresh gateway:
```bash
python3 tools/provision.py mint-token # API token file-drops + gateway restart; updates .env
python3 tools/provision.py provision # secret provider + DB connection + alarm journal + sim tags
```
- `mint-token` writes an `api-token` config resource under `ignition/gateway/config/`,
patches the `Authenticated > API` security levels into gateway read/write permissions,
restarts the gateway (if running; otherwise the token loads on next boot), and saves
`IGN_API=Buildathon:<secret>` to `.env` (gitignored). Only the SHA-256 hash of the
secret is stored in the config files.
- `provision` is idempotent — it skips resources that already exist. It creates:
- file secret provider `local` (MariaDB password lives in the gitignored file
`ignition/gateway/config/secrets/mariadb_password`, referenced by the connection —
the 8.3 API only accepts encrypted or referenced secrets)
- database connection `Buildathon_DB``jdbc:mariadb://db:3306/ignition`
- alarm journal `Journal` → tables `PrimeControls_alarm_events` / `PrimeControls_alarm_event_data`
- imports `test-data/simulation_tags.json` into the `default` tag provider
Ad-hoc API calls use one header: `curl -H "X-Ignition-API-Token: $IGN_API" $GATEWAY_URL/openapi.json`
(source `.env` first).
Two steps remain manual (Designer-only): creating the `Buildathon` Perspective project
(step 3 below) and installing the simulator timer script ([test-data/README.md](test-data/README.md)).
## Manual setup reference (what provision.py does, plus the Designer steps)
### 1. Database connection (MariaDB) — automated
Gateway web UI → **Config → Databases → Connections → Create new Database Connection**
| Setting | Value |
| ----------- | -------------------------------- |
| Name | `Buildathon_DB` |
| Driver | MariaDB |
| Connect URL | `jdbc:mariadb://db:3306/ignition` |
| Username | `ignition` |
| Password | `ignition` |
Note the host is `db` (the compose service name), **not** `localhost` — the gateway reaches
MariaDB over the compose network. Save and confirm the status shows **Valid**.
Ignition 8.3 ships the MariaDB JDBC driver, so no driver install is needed.
### 2. Alarm journal profile — automated
Gateway web UI → **Config → Alarming → Journal → Create new Alarm Journal Profile**
| Setting | Value |
| ------------ | --------------------------- |
| Name | `Journal` (any name works) |
| Type | Database |
| Datasource | `Buildathon_DB` |
| Table prefix | `PrimeControls_` |
Leave the event filters at defaults (store everything) so the analytics have full data.
The journal auto-creates `PrimeControls_alarm_events` and `PrimeControls_alarm_event_data`
in MariaDB the first time an alarm event occurs.
### 3. Perspective project — manual
1. Gateway web UI → **Config → Projects → Create new Project** (or Designer → File → New Project)
- Name: `Buildathon`
2. Open it in the Designer (launch from <http://localhost:8088> → Designer launcher),
then set the project default database: **Project → Project Properties → General →
Default Database** → `Buildathon_DB`. Save the project.
Named queries and bindings that use the "default" database now hit MariaDB.
## Test data
See [test-data/README.md](test-data/README.md) — imports simulation memory tags with alarm
configs and a Jython script that generates realistic alarm activity (baseline alarms across
5 plant areas / 3 priorities, chattering, standing, fleeting, and flood-burst patterns).
## Reset to a completely fresh gateway
Gateway state is repo files now, so `docker compose down -v` alone no longer wipes the
gateway — it only removes the containers and the MariaDB volume. To verify the project
export imports cleanly on a fresh install (the contest judging scenario), set the gateway
files aside and rebuild:
```bash
docker compose down -v # containers + MariaDB volume
mv ignition/gateway ignition/gateway.bak # keep your current state for rollback
mkdir -p ignition/gateway/commission ignition/gateway/config ignition/gateway/projects
cp ignition/gateway.bak/commission/commissioning.json ignition/gateway/commission/
docker compose up -d # boots factory-fresh, auto-commissions
python3 tools/provision.py mint-token # old token lived in gateway.bak
python3 tools/provision.py provision
```
Then import your project export to prove it stands alone. Roll back to your working
state with `docker compose down && rm -rf ignition/gateway && mv ignition/gateway.bak
ignition/gateway && docker compose up -d` (MariaDB journal data is gone either way after
`-v` — the sim regenerates it).
A plain `docker compose down` / `up -d` restarts with everything intact.
## Notes
- Max JVM heap is 2 GB (`-m 2048` runtime arg in the compose `command`).
- The 8.3 image's data dir is `/usr/local/bin/ignition/data`; only `commissioning.json`,
`config/`, and `projects/` are bind-mounted from `ignition/gateway/` (see the
gateway-as-files section above).
- `ignition` waits on the MariaDB healthcheck before starting, so the datasource is
reachable as soon as the gateway is up.

69
docker-compose.yml Normal file
View File

@@ -0,0 +1,69 @@
services:
ignition:
image: inductiveautomation/ignition:8.3.7
container_name: buildathon-ignition
ports:
- "8088:8088"
environment:
ACCEPT_IGNITION_EULA: "Y"
GATEWAY_ADMIN_USERNAME: admin
GATEWAY_ADMIN_PASSWORD: password
IGNITION_EDITION: standard
DISABLE_QUICKSTART: "true"
# Run the gateway as the HOST dev uid/gid (primebench pattern): started
# as root (user 0:0), the official entrypoint chowns the bind mounts to
# IGNITION_UID/GID and drops privileges — repo-mapped gateway files stay
# owned by you, so host-side edits need no chown dance (WSL2 included).
IGNITION_UID: "${IGNITION_UID:-1000}"
IGNITION_GID: "${IGNITION_GID:-1000}"
TZ: America/Chicago
user: "0:0"
# Runtime args: gateway name + 2GB max JVM heap (8.3 uses the -m flag, not an env var)
command: >
-n buildathon
-m 2048
volumes:
# Gateway-as-files (primebench/TestingPlatform pattern): commissioning is
# a version-controlled FILE and only the durable state (config/, projects/)
# is bind-mounted from the repo — a container recreate can never wipe it
# and the gateway never re-commissions. Internal db/var/logs stay
# ephemeral in-container. Gateway config, tags, timers, and Perspective
# views are therefore ordinary files under ignition/gateway/.
- ./ignition/gateway/commission/commissioning.json:/usr/local/bin/ignition/data/commissioning.json
- ./ignition/gateway/config:/usr/local/bin/ignition/data/config
- ./ignition/gateway/projects:/usr/local/bin/ignition/data/projects
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- buildathon
db:
image: mariadb:11.8
container_name: buildathon-db
environment:
MARIADB_ROOT_PASSWORD: password
MARIADB_DATABASE: ignition
MARIADB_USER: ignition
MARIADB_PASSWORD: ignition
ports:
# localhost only, for inspecting with a SQL client
- "127.0.0.1:3306:3306"
volumes:
- db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
start_period: 15s
interval: 5s
timeout: 5s
retries: 12
restart: unless-stopped
networks:
- buildathon
networks:
buildathon:
volumes:
db-data:

View File

@@ -0,0 +1,5 @@
{
"isCommissioned": "COMMISSIONED",
"connections.useSsl": "false",
"eulaSetup.eula": "B3RM3rHPH6fHm8owWAEx/YnCk04FsYkXTDX8DOl4zQI="
}

Binary file not shown.

View File

@@ -0,0 +1 @@
4a724368-db9a-4b8f-aac6-8657ca872bcf

View File

@@ -0,0 +1,25 @@
{
"ackPipeline": "",
"activePipeline": "",
"alarmOnActivity": true,
"alarmOnMetrics": false,
"alarmOnTasks": true,
"connectedClientsError": 100,
"connectedClientsWarning": 50,
"connectionError": 15,
"connectionWarning": 5,
"cpuError": 90,
"cpuWarning": 70,
"dbConnUtilError": 100,
"dbConnUtilWarning": 80,
"errPerHourError": 60,
"errPerHourWarning": 20,
"errPerMinError": 5,
"errPerMinWarning": 2,
"errorPriority": "High",
"memError": 90,
"memWarning": 70,
"perspectiveSessionsError": 100,
"perspectiveSessionsWarning": 50,
"warningPriority": "Low"
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:40Z"
},
"lastModificationSignature": "e245ae847d6497c0d1bb753d73634100cb71677d52fe0e09dbb8d53d66aa9cee"
}
}

View File

@@ -0,0 +1,17 @@
{
"agentSettings": {
"forwardLeasedLicense": false,
"httpConnectTimeout": 10,
"httpReadTimeout": 60,
"sendStatsInterval": 45
},
"controllerSettings": {
"archiveLocationMode": "Automatic",
"backupRetentionAge": 0,
"backupRetentionTimeUnit": "Days",
"eventTableName": "agent_events",
"lowDiskThresholdMB": 1024,
"maxRetainedBackupCount": 5
},
"installMode": "NotInstalled"
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:40Z"
},
"lastModificationSignature": "763a41b552f6e7cff1ecf07d939f010b641f72109962ef5f46cd4103dea36f43"
}
}

View File

@@ -0,0 +1,39 @@
{
"defaultDeviceRolePermissionMappings": [
{
"permissions": [
"Browse",
"Read"
],
"role": "Anonymous"
},
{
"permissions": [
"Browse",
"Read",
"Write",
"Call"
],
"role": "AuthenticatedUser"
}
],
"defaultTagProviderRolePermissionMappings": [
{
"permissions": [
"Browse",
"Read"
],
"role": "Anonymous"
},
{
"permissions": [
"Browse",
"Read",
"Write",
"Call"
],
"role": "AuthenticatedUser"
}
],
"tagProviderRolePermissionMappings": {}
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:38Z"
},
"lastModificationSignature": "4be4ea51de3e1c2c6cae54ad76543afccc9e11a2806110b8bd8ca9c25af5e747"
}
}

View File

@@ -0,0 +1,4 @@
{
"defaultAuthProfileCreated": true,
"defaultOpcUaConnectionCreated": true
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "unknown",
"timestamp": "2026-07-16T15:30:53Z"
},
"lastModificationSignature": "78f6fd87284fcb580b686686b7cf758bc4c34459bc1b4a4b38049e06cd01d5f9"
}
}

View File

@@ -0,0 +1,30 @@
{
"advanced": {
"exposedTagsEnabled": false,
"gdsPushEnabled": false,
"maxSessionCount": 100
},
"authentication": {
"anonymousAccessAllowed": false,
"authenticationProfile": "opcua-module"
},
"endpoint": {
"bindAddresses": [
"localhost"
],
"bindPort": 62541,
"endpointAddresses": [
"\u003chostname\u003e",
"\u003clocalhost\u003e"
],
"messageSecurityModes": [
"SignAndEncrypt"
],
"securityPolicies": [
"Basic256Sha256"
]
},
"redundancy": {
"readOnlyWhenInactive": false
}
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:39Z"
},
"lastModificationSignature": "e4b8cd2df70c247643fb3678b8c12e329076ec4a381e2b0c93cd1d12def4cb3d"
}
}

View File

@@ -0,0 +1,4 @@
{
"entrypoint": "index.css",
"isPrivate": false
}

View File

@@ -0,0 +1,8 @@
@import "./variables.css";
@import "../light/fonts.css";
@import "../dark/globals.css";
@import "../light/app/index.css";
@import "../light/common/index.css";
@import "../light/designer/index.css";
@import "../light/palette/index.css";
@import "../dark/palette/index.css";

View File

@@ -0,0 +1,19 @@
{
"scope": "G",
"description": "The dark-cool theme for Perspective.",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json",
"index.css",
"variables.css"
],
"attributes": {
"lastModification": {
"actor": "theme-manager",
"timestamp": "2026-07-16T15:30:38Z"
},
"lastModificationSignature": "ff17cec25d396dfe55d1585865084f4fe83ca211efefc0d6fc04f59afdcb93a4"
}
}

View File

@@ -0,0 +1,15 @@
@import "../dark/variables.css";
:root {
/* Neutrals */
--neutral-10: #121619; /* cool-100 */
--neutral-20: #21272A; /* cool-90 */
--neutral-30: #343A3F; /* cool-80 */
--neutral-40: #4D5358; /* cool-70 */
--neutral-50: #697077; /* cool-60 */
--neutral-60: #878D96; /* cool-50 */
--neutral-70: #A2A9B0; /* cool-40 */
--neutral-80: #C1C7CD; /* cool-30 */
--neutral-90: #DDE1E6; /* cool-20 */
--neutral-100: #F2F4F8; /* cool-10 */
}

View File

@@ -0,0 +1,4 @@
{
"entrypoint": "index.css",
"isPrivate": false
}

View File

@@ -0,0 +1,8 @@
@import "./variables.css";
@import "../light/fonts.css";
@import "../dark/globals.css";
@import "../light/app/index.css";
@import "../light/common/index.css";
@import "../light/designer/index.css";
@import "../light/palette/index.css";
@import "../dark/palette/index.css";

View File

@@ -0,0 +1,19 @@
{
"scope": "G",
"description": "The dark-warm theme for Perspective.",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json",
"index.css",
"variables.css"
],
"attributes": {
"lastModification": {
"actor": "theme-manager",
"timestamp": "2026-07-16T15:30:38Z"
},
"lastModificationSignature": "41e8940d4061e52b7daf1e90d59bf58f76c6d4e6bedfc6b36d220f0d3df8a896"
}
}

View File

@@ -0,0 +1,15 @@
@import "../dark/variables.css";
:root {
/* Neutrals */
--neutral-10: #171414; /* warm-100 */
--neutral-20: #272525; /* warm-90 */
--neutral-30: #3C3838; /* warm-80 */
--neutral-40: #565151; /* warm-70 */
--neutral-50: #736F6F; /* warm-60 */
--neutral-60: #8F8B8B; /* warm-50 */
--neutral-70: #ADA8A8; /* warm-40 */
--neutral-80: #CAC5C4; /* warm-30 */
--neutral-90: #E5E0DF; /* warm-20 */
--neutral-100: #F7F3F2; /* warm-10 */
}

View File

@@ -0,0 +1,4 @@
{
"entrypoint": "index.css",
"isPrivate": false
}

View File

@@ -0,0 +1,7 @@
@import "./variables.css";
@import "../light/fonts.css";
@import "../light/globals.css";
@import "../light/app/index.css";
@import "../light/common/index.css";
@import "../light/designer/index.css";
@import "../light/palette/index.css";

View File

@@ -0,0 +1,19 @@
{
"scope": "G",
"description": "The light-cool theme for Perspective.",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json",
"index.css",
"variables.css"
],
"attributes": {
"lastModification": {
"actor": "theme-manager",
"timestamp": "2026-07-16T15:30:38Z"
},
"lastModificationSignature": "5f7f9340044a5ea8c8d54ea456e14215b9fef052d33135819eead5965c00d2fb"
}
}

View File

@@ -0,0 +1,15 @@
@import "../light/variables.css";
:root {
/* Neutrals */
--neutral-10: #F2F4F8; /* cool-10 */
--neutral-20: #DDE1E6; /* cool-20 */
--neutral-30: #C1C7CD; /* cool-30 */
--neutral-40: #A2A9B0; /* cool-40 */
--neutral-50: #878D96; /* cool-50 */
--neutral-60: #697077; /* cool-60 */
--neutral-70: #4D5358; /* cool-70 */
--neutral-80: #343A3F; /* cool-80 */
--neutral-90: #21272A; /* cool-90 */
--neutral-100: #121619; /* cool-100 */
}

View File

@@ -0,0 +1,4 @@
{
"entrypoint": "index.css",
"isPrivate": false
}

View File

@@ -0,0 +1,7 @@
@import "./variables.css";
@import "../light/fonts.css";
@import "../light/globals.css";
@import "../light/app/index.css";
@import "../light/common/index.css";
@import "../light/designer/index.css";
@import "../light/palette/index.css";

View File

@@ -0,0 +1,19 @@
{
"scope": "G",
"description": "The light-warm theme for Perspective.",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json",
"index.css",
"variables.css"
],
"attributes": {
"lastModification": {
"actor": "theme-manager",
"timestamp": "2026-07-16T15:30:38Z"
},
"lastModificationSignature": "4e325d4061f679d63f4065ef94a899421e77ffa3357e035b31c1abdc7e811eb5"
}
}

View File

@@ -0,0 +1,16 @@
@import "../light/variables.css";
:root {
/* Neutrals */
--neutral-10: #F7F3F2; /* warm-10 */
--neutral-20: #E5E0DF; /* warm-20 */
--neutral-30: #CAC5C4; /* warm-30 */
--neutral-40: #ADA8A8; /* warm-40 */
--neutral-50: #8F8B8B; /* warm-50 */
--neutral-60: #736F6F; /* warm-60 */
--neutral-70: #565151; /* warm-70 */
--neutral-80: #3C3838; /* warm-80 */
--neutral-90: #272525; /* warm-90 */
--neutral-100: #171414; /* warm-100 */
}

View File

@@ -0,0 +1,6 @@
{
"chartRecordingEnabled": false,
"pruneAge": 7,
"pruneAgeUnits": "DAY",
"recordingsPerChart": 5
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:37Z"
},
"lastModificationSignature": "daa9add1f64df9be0f907825a3584e64188ab973307747ecadd18007994f155c"
}
}

View File

@@ -0,0 +1,7 @@
{
"title": "Core",
"description": "Core collection of locally managed Gateway configuration resources",
"enabled": true,
"inheritable": true,
"parent": "external"
}

View File

@@ -0,0 +1,16 @@
{
"profile": {
"queryOnly": false,
"type": "DATASOURCE"
},
"settings": {
"advanced": {
"dataTableName": "PrimeControls_alarm_event_data",
"tableName": "PrimeControls_alarm_events"
},
"datasource": "Buildathon_DB",
"events": {
"minPriority": "Diagnostic"
}
}
}

View File

@@ -0,0 +1,19 @@
{
"scope": "A",
"description": "Build-a-Thon alarm journal -\u003e Buildathon_DB, PrimeControls_ table prefix",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "api-token:Buildathon:172.23.0.1",
"timestamp": "2026-07-16T15:43:41Z"
},
"uuid": "a4c6cf10-ece5-446b-8afd-2cf296941174",
"lastModificationSignature": "462e2561f20f9397e3e8e66374dc523b0aa8bee67677dac2d4b77413a46b5966",
"enabled": true
}
}

View File

@@ -0,0 +1,35 @@
{
"profile": {
"secureChannelRequired": false,
"securityLevels": [
{
"children": [
{
"children": [
{
"children": [],
"name": "Access"
},
{
"children": [],
"name": "Read"
},
{
"children": [],
"name": "Write"
}
],
"name": "API"
}
],
"description": "Represents a user who has been authenticated by the system.",
"name": "Authenticated"
}
],
"timestamp": 1784216310176,
"type": "basic-token"
},
"settings": {
"tokenHash": "gRWFOVFZWoJU0K2ZC7wscQR-u0fJgCDYW27643fMe8I"
}
}

View File

@@ -0,0 +1,14 @@
{
"scope": "A",
"description": "",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"uuid": "5084e69e-49cc-4117-a144-ec3a6fff6ec1",
"enabled": true
}
}

View File

@@ -0,0 +1,16 @@
{
"appIcon": null,
"appIconName": null,
"appIconSize": null,
"backgroundColor": "#697077",
"buttonColor": "#0C7BB3",
"buttonTextColor": "#FFFFFF",
"enabled": false,
"favicon": null,
"faviconName": null,
"faviconSize": null,
"logo": null,
"logoName": null,
"logoType": null,
"textColor": "#FFFFFF"
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:29Z"
},
"lastModificationSignature": "a27c1522446826456786b168545475859530e461d691a0efb13de20461c35c85"
}
}

View File

@@ -0,0 +1,32 @@
{
"connectURL": "jdbc:mariadb://db:3306/ignition",
"connectionProps": "",
"connectionResetParams": "",
"defaultTransactionLevel": "DEFAULT",
"driver": "MariaDB",
"evictionRate": -1,
"evictionTests": 3,
"evictionTime": 1800000,
"failoverMode": "STANDARD",
"includeSchemaInTableName": false,
"password": {
"data": {
"providerName": "local",
"secretName": "mariadb-password"
},
"type": "Referenced"
},
"poolInitSize": 0,
"poolMaxActive": 8,
"poolMaxIdle": 8,
"poolMaxWait": 5000,
"poolMinIdle": 0,
"slowQueryLogThreshold": 60000,
"testOnBorrow": true,
"testOnReturn": false,
"testWhileIdle": false,
"translator": "MYSQL",
"username": "ignition",
"validationQuery": "SELECT 1",
"validationSleepTime": 10000
}

View File

@@ -0,0 +1,14 @@
{
"scope": "A",
"description": "Build-a-Thon MariaDB (alarm journal + dashboard queries)",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"uuid": "a7e8b14a-c10f-4d8e-bd40-ff3162db0258",
"enabled": true
}
}

View File

@@ -0,0 +1,10 @@
{
"classname": "com.mysql.cj.jdbc.Driver",
"defaultPropInstructions": "There is an extensive list of extra connection properties available for MySQL Connector/J. See \u003ca href\u003d\u0027http://dev.mysql.com/doc/connectors/en/connector-j-reference-configuration-properties.html\u0027\u003ethe documentation\u003c/a\u003e for a table describing all connection properties.\u003cbr\u003eA default \u003ctt\u003eserverTimezone\u003c/tt\u003e value (taken from the gateway) will be appended to the connection string if one is not specified.",
"defaultProps": "zeroDateTimeBehavior\u003dCONVERT_TO_NULL;connectTimeout\u003d120000;socketTimeout\u003d120000;useSSL\u003dfalse;allowPublicKeyRetrieval\u003dtrue;rewriteBatchedStatements\u003dtrue;disableMariaDbDriver",
"defaultTranslator": "MYSQL",
"defaultValidationQuery": "SELECT 1",
"type": "MYSQL",
"urlFormat": "jdbc:mysql://localhost:3306/test",
"urlInstructions": "\u003cbr/\u003eThe format of the MySQL connect URL is:\u003cbr\u003e\u003ccode\u003ejdbc:mysql://\u003cb\u003ehost\u003c/b\u003e:\u003cb\u003eport\u003c/b\u003e/\u003cb\u003edatabase\u003c/b\u003e\u003c/code\u003e\u003cbr\u003eWith the three parameters (in bold) \u003cul style\u003d\"list-style-type:none;margin-left:10px;\"\u003e\u003cli\u003e\u003cb\u003ehost\u003c/b\u003e: The host name or IP address of the database server.\u003c/li\u003e\u003cli\u003e\u003cb\u003eport\u003c/b\u003e: The port that the database server is running on. MySQL default port is \u003cb\u003e3306\u003c/b\u003e.\u003c/li\u003e\u003cli\u003e\u003cb\u003edatabase\u003c/b\u003e: The name of the logical database that you are connecting to on the MySQL server.\u003c/li\u003e\u003c/ul\u003e"
}

View File

@@ -0,0 +1,13 @@
{
"scope": "A",
"description": "The official MySQL JDBC Driver, Connector/J.",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"uuid": "3c58bd26-e025-4610-ab9e-ed6d01880972"
}
}

View File

@@ -0,0 +1,10 @@
{
"classname": "oracle.jdbc.driver.OracleDriver",
"defaultPropInstructions": "",
"defaultProps": "",
"defaultTranslator": "ORACLE",
"defaultValidationQuery": "SELECT 1 FROM DUAL",
"type": "ORACLE",
"urlFormat": "jdbc:oracle:thin:@localhost:1521:test",
"urlInstructions": "\u003cbr/\u003eThe format of the Oracle connect URL is:\u003cbr/\u003e\u003ccode\u003ejdbc:oracle:thin:@\u003cb\u003ehost\u003c/b\u003e:\u003cb\u003eport\u003c/b\u003e:\u003cb\u003eSID\u003c/b\u003e\u003c/code\u003e\u003cbr/\u003eWith the three parameters (in bold) \u003cul style\u003d\"list-style-type:none;margin-left:10px;\"\u003e\u003cli\u003e\u003cb\u003ehost\u003c/b\u003e: The host name or IP address of the database server.\u003c/li\u003e\u003cli\u003e\u003cb\u003eport\u003c/b\u003e: The port that the database server is running on. Oracle\u0027s default port is \u003cb\u003e1521\u003c/b\u003e.\u003c/li\u003e\u003cli\u003e\u003cb\u003eSID\u003c/b\u003e: the system ID that identifies the database to connect to.\u003c/li\u003e\u003c/ul\u003e"
}

View File

@@ -0,0 +1,13 @@
{
"scope": "A",
"description": "The Oracle Database JDBC driver.",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"uuid": "9a84d6a5-f26e-4b56-a8d4-5c590d2d9f9f"
}
}

View File

@@ -0,0 +1,10 @@
{
"classname": "org.sqlite.JDBC",
"defaultPropInstructions": "No extra connection parameters are recommended for SQLite",
"defaultProps": "",
"defaultTranslator": "SQLITE",
"defaultValidationQuery": "SELECT 1",
"type": "SQLITE",
"urlFormat": "jdbc:sqlite:C:/Path/To/File.db",
"urlInstructions": "\u003cbr/\u003eThe format of the SQLite connect URL is:\u003cbr/\u003e\u003ccode\u003ejdbc:sqlite:C:/Path/To/File.db\u003c/code\u003e\u003cbr/\u003e\u003ccode\u003ejdbc:sqlite:/path/on/linux/File.db\u003c/code\u003e\u003cbr/\u003e\u003cbr/\u003eUse \u003ccode\u003e${data}\u003c/code\u003e or \u003ccode\u003e${local}\u003c/code\u003e as a placeholder for the Ignition Gateway\u0027s data directory or local directory, respectively, as seen below:\u003cbr/\u003e\u003ccode\u003ejdbc:sqlite:${data}/File.db\u003c/code\u003e\u003cbr/\u003e\u003ccode\u003ejdbc:sqlite:${local}/Folder/File.db\u003c/code\u003e\u003cbr/\u003e\u003cbr/\u003eUse \u003ccode\u003ejdbc:sqlite::memory:\u003c/code\u003e for a temporary database.\u003cbr/\u003e"
}

View File

@@ -0,0 +1,13 @@
{
"scope": "A",
"description": "Driver for the popular embedded database system.",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"uuid": "fc86f402-2c45-48a9-82c8-c3b8f2606d60"
}
}

View File

@@ -0,0 +1,26 @@
{
"alterTable": "ALTER TABLE {tablename} {alterdef}",
"alterTableColumnDef": "ADD COLUMN {columnname} {type}",
"autoIncTypeDef": "{type} NOT NULL AUTO_INCREMENT",
"blobType": "VARBINARY",
"boolType": "INT",
"columnQuoteChar": "\"",
"createIndex": "CREATE INDEX {indexname} ON {tablename}({columnname})",
"createTable": "CREATE TABLE {tablename} ({creationdef}{primarykeydef})",
"currentTimeQuery": "SELECT CURRENT_TIMESTAMP",
"datetimeType": "DATETIME",
"fetchKeyQuery": "",
"i1Type": "INT",
"i2Type": "INT",
"i4Type": "INT",
"i8Type": "BIGINT",
"limit": "LIMIT {limit}",
"limitClausePosition": "Back",
"primaryKeyDef": "PRIMARY KEY ({columnname})",
"r4Type": "FLOAT",
"r8Type": "DOUBLE",
"stringType": "VARCHAR(255)",
"supportsRGK": true,
"tableListFilter": "",
"textType": ""
}

View File

@@ -0,0 +1,17 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:45Z"
},
"uuid": "1e331d89-8750-43d7-8b99-3c356dafd1e7",
"lastModificationSignature": "82cdefcf34adc41a68ce59d1e0540e10be30e90cef214f6ad89e6b28fa8dcbb2"
}
}

View File

@@ -0,0 +1,26 @@
{
"alterTable": "ALTER TABLE {tablename} ADD {alterdef}",
"alterTableColumnDef": "{columnname} {type}",
"autoIncTypeDef": "{type} IDENTITY(1, 1)",
"blobType": "VARBINARY",
"boolType": "INT",
"columnQuoteChar": "\"",
"createIndex": "CREATE INDEX {indexname} ON {tablename}({columnname})",
"createTable": "CREATE TABLE {tablename} ({creationdef}{primarykeydef})",
"currentTimeQuery": "SELECT CURRENT_TIMESTAMP",
"datetimeType": "DATETIME",
"fetchKeyQuery": "",
"i1Type": "INT",
"i2Type": "INT",
"i4Type": "INT",
"i8Type": "BIGINT",
"limit": "TOP {limit}",
"limitClausePosition": "Front",
"primaryKeyDef": "PRIMARY KEY CLUSTERED ({columnname})",
"r4Type": "FLOAT(10)",
"r8Type": "DOUBLE PRECISION",
"stringType": "NVARCHAR(255)",
"supportsRGK": true,
"tableListFilter": "",
"textType": "NVARCHAR(MAX)"
}

View File

@@ -0,0 +1,17 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:45Z"
},
"uuid": "a666f397-7449-41af-923a-faa0a2fe6375",
"lastModificationSignature": "a4f7db04ce6a14ea5af5a34a93655cd4ba1b17cd9b6fbb7fca9cfae9231d9c50"
}
}

View File

@@ -0,0 +1,26 @@
{
"alterTable": "ALTER TABLE {tablename} {alterdef}",
"alterTableColumnDef": "ADD COLUMN {columnname} {type}",
"autoIncTypeDef": "{type} NOT NULL AUTO_INCREMENT",
"blobType": "VARBINARY",
"boolType": "INT",
"columnQuoteChar": "`",
"createIndex": "CREATE INDEX {indexname} ON {tablename}({columnname})",
"createTable": "CREATE TABLE {tablename} ({creationdef}{primarykeydef})",
"currentTimeQuery": "SELECT CURRENT_TIMESTAMP",
"datetimeType": "DATETIME",
"fetchKeyQuery": "",
"i1Type": "INT",
"i2Type": "INT",
"i4Type": "INT",
"i8Type": "BIGINT",
"limit": "LIMIT {limit}",
"limitClausePosition": "Back",
"primaryKeyDef": "PRIMARY KEY ({columnname})",
"r4Type": "FLOAT",
"r8Type": "DOUBLE",
"stringType": "VARCHAR(255)",
"supportsRGK": true,
"tableListFilter": "",
"textType": "TEXT"
}

View File

@@ -0,0 +1,17 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:45Z"
},
"uuid": "d89b8e62-4291-424e-bbe1-c02a9d59a68a",
"lastModificationSignature": "d1f86e5721ace6ef73db3be16af8ad8c75f407eeb4d12ac56819895613cb7b8e"
}
}

View File

@@ -0,0 +1,28 @@
{
"alterTable": "ALTER TABLE {tablename} ADD ({alterdef})",
"alterTableColumnDef": "{columnname} {type}",
"autoIncTypeDef": "{type} NOT NULL",
"blobType": "VARBINARY",
"boolType": "INT",
"columnQuoteChar": "\"",
"createAutoIncSequence": "CREATE SEQUENCE {tablename}_seq START WITH 1 INCREMENT BY 1",
"createAutoIncTrigger": "CREATE TRIGGER {tablename}_trig \nBEFORE INSERT ON {tablename} \nREFERENCING NEW AS NEW\nFOR EACH ROW \nBEGIN \n SELECT {tablename}_seq.NEXTVAL \n INTO :NEW.{columnname} FROM DUAL;\nEND;",
"createIndex": "CREATE INDEX {indexname} ON {tablename}({columnname})",
"createTable": "CREATE TABLE {tablename} ({creationdef}{primarykeydef})",
"currentTimeQuery": "SELECT CURRENT_TIMESTAMP FROM DUAL",
"datetimeType": "TIMESTAMP",
"fetchKeyQuery": "SELECT {tablename}_seq.CURRVAL FROM DUAL",
"i1Type": "INT",
"i2Type": "INT",
"i4Type": "INT",
"i8Type": "INT",
"limit": "ROWNUM \u003c\u003d {limit}",
"limitClausePosition": "Wrap",
"primaryKeyDef": "PRIMARY KEY ({columnname})",
"r4Type": "FLOAT",
"r8Type": "DOUBLE PRECISION",
"stringType": "VARCHAR2(255)",
"supportsRGK": false,
"tableListFilter": "SYS_INFO*;*SYSTEM*;WWV*;*$*;DBA*;LOGMNR*;ORDDCM*;APEX*;ALL_SA*;DATABASE*;DV_*;GSM*;HELP;MVIEW*;ORD_*;PRODUCT_PRIVS;REDO_*;SCHEDULER_*;SERVICE*;SI_*;SQLPLUS*;SYS_*;USER_SA*;VERIFY_HISTORY;VNCR;WLM_*;XML_*;CLOUD;REGION;CHANGE_LOG*",
"textType": "NCLOB"
}

View File

@@ -0,0 +1,17 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:45Z"
},
"uuid": "d81d8d01-62c7-4efe-9117-8a9470d65d61",
"lastModificationSignature": "5045a098f80eb43b87c5dbe6a0d276fb71bed596a3d83992ecd8af02474e4d5a"
}
}

View File

@@ -0,0 +1,26 @@
{
"alterTable": "ALTER TABLE {tablename} {alterdef}",
"alterTableColumnDef": "ADD COLUMN {columnname} {type}",
"autoIncTypeDef": "SERIAL NOT NULL",
"blobType": "BYTEA",
"boolType": "INT",
"columnQuoteChar": "\"",
"createIndex": "CREATE INDEX {indexname} ON {tablename}({columnname})",
"createTable": "CREATE TABLE {tablename} ({creationdef}{primarykeydef})",
"currentTimeQuery": "SELECT CURRENT_TIMESTAMP",
"datetimeType": "TIMESTAMP",
"fetchKeyQuery": "",
"i1Type": "INT",
"i2Type": "INT",
"i4Type": "INT",
"i8Type": "BIGINT",
"limit": "LIMIT {limit}",
"limitClausePosition": "Back",
"primaryKeyDef": "PRIMARY KEY ({columnname})",
"r4Type": "FLOAT",
"r8Type": "DOUBLE PRECISION",
"stringType": "VARCHAR(255)",
"supportsRGK": true,
"tableListFilter": "",
"textType": "TEXT"
}

View File

@@ -0,0 +1,17 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:45Z"
},
"uuid": "a0ce5af8-1853-474b-b13e-b60f86208721",
"lastModificationSignature": "d1525500146320d62b44b4a125e079dd1dcf4060f1253e9fc53a1996922d98ec"
}
}

View File

@@ -0,0 +1,26 @@
{
"alterTable": "ALTER TABLE {tablename} {alterdef}",
"alterTableColumnDef": "ADD COLUMN {columnname} {type}",
"autoIncTypeDef": "INTEGER PRIMARY KEY",
"blobType": "BLOB",
"boolType": "INTEGER",
"columnQuoteChar": "\"",
"createIndex": "CREATE INDEX {indexname} ON {tablename}({columnname})",
"createTable": "CREATE TABLE {tablename} ({creationdef}{primarykeydef})",
"currentTimeQuery": "SELECT CURRENT_TIMESTAMP",
"datetimeType": "TEXT",
"fetchKeyQuery": "",
"i1Type": "INTEGER",
"i2Type": "INTEGER",
"i4Type": "INTEGER",
"i8Type": "INTEGER",
"limit": "LIMIT {limit}",
"limitClausePosition": "Back",
"primaryKeyDef": "",
"r4Type": "REAL",
"r8Type": "REAL",
"stringType": "TEXT",
"supportsRGK": true,
"tableListFilter": "",
"textType": "TEXT"
}

View File

@@ -0,0 +1,17 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:45Z"
},
"uuid": "66c24183-5c08-4936-b3a5-3c4614a278cc",
"lastModificationSignature": "2fe841bd28a6410bdcc238b6827d58f6b0127e93d4d0ad95f19ae7fb40dd6505"
}
}

View File

@@ -0,0 +1,5 @@
{
"historianName": "Edge Historian",
"projectName": "Edge",
"visualizationName": "VISION"
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:29Z"
},
"lastModificationSignature": "a9072a0f8dbddc992d137a2f2e4afba9005c389e902fafea10566f4dcf3dd407"
}
}

View File

@@ -0,0 +1,3 @@
{
"proxyRules": []
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "8.3-migration",
"timestamp": "2026-07-16T15:30:28Z"
},
"lastModificationSignature": "e6460860e9252aaee999fa97f0b37f1b9224f46f823bc38765dcbbe42bfa0e08"
}
}

View File

@@ -0,0 +1,39 @@
{
"queueSettings": [
{
"description": "Generic Gateway Network queue",
"friendlyName": "Default Queue",
"maxActive": -1,
"queueId": "_default_",
"timeoutMillis": 60000
},
{
"description": "Handles gateway network diagnostic information messages",
"friendlyName": "Diagnostic Info Queue",
"maxActive": -1,
"queueId": "diagnosticInfoQueue",
"timeoutMillis": 300000
},
{
"description": "Handles results for remote service calls over the Gateway Network",
"friendlyName": "Call Results Queue",
"maxActive": -1,
"queueId": "_rpcReturn_",
"timeoutMillis": 60000
},
{
"description": "Handles messages that take up to an hour to deliver",
"friendlyName": "Long Wait Queue",
"maxActive": -1,
"queueId": "longWaitQueue",
"timeoutMillis": 3600000
},
{
"description": "Forwards requests through a proxy Gateway",
"friendlyName": "Proxy Queue",
"maxActive": -1,
"queueId": "_proxy_",
"timeoutMillis": 3600000
}
]
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "8.3-migration",
"timestamp": "2026-07-16T15:30:28Z"
},
"lastModificationSignature": "eeed2ff39e63f85d569c6f47cf6b88aa978da306d2079fbba118b5f3d102ff4e"
}
}

View File

@@ -0,0 +1,19 @@
{
"allowIncoming": true,
"allowJavaSerialization": false,
"allowedProxyHops": 0,
"dataChannelQueueSize": 50,
"dataChannelThreadPoolMaxSize": 100,
"incomingPingMaxMissed": 12,
"incomingPingRateMillis": 5000,
"incomingPingTimeoutMillis": 300,
"overloadWaitSecs": 60,
"proxyInterceptServiceCalls": false,
"receiveQueueMax": 100,
"requireSSL": true,
"requireTwoWayAuth": true,
"securityPolicy": "ApprovedOnly",
"tempFilesMaxAgeHours": 24,
"websocketSessionIdleTimeout": 30000,
"whitelist": ""
}

View File

@@ -0,0 +1,17 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:52Z"
},
"lastModificationSignature": "5dd9990c2fc6b9407a23b74122b1fc5e9b9063206c4a7f76a38829dd7461c9a8",
"enabled": true
}
}

View File

@@ -0,0 +1,5 @@
{
"liveEventLimit": 5,
"notifyInitialEvents": false,
"startupSuppressionTime": 10
}

View File

@@ -0,0 +1,16 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "default",
"timestamp": "2026-07-16T15:30:45Z"
},
"lastModificationSignature": "25a28dfdc89237ed329fb9975a0cf881b661a7add251b941dd73e739511adc0a"
}
}

View File

@@ -0,0 +1,62 @@
{
"profile": {
"securityLevelRules": {
"nodes": []
},
"type": "internal",
"userAttributeMapper": {
"email": {
"config": {
"attributePath": "email"
},
"type": "direct"
},
"firstName": {
"config": {
"attributePath": "given_name"
},
"type": "direct"
},
"id": {
"config": {
"attributePath": "sub"
},
"type": "direct"
},
"lastName": {
"config": {
"attributePath": "family_name"
},
"type": "direct"
},
"roles": {
"config": {
"attributePath": "roles"
},
"type": "direct"
},
"userName": {
"config": {
"attributePath": "preferred_username"
},
"type": "direct"
}
},
"userGrants": {
"id": {},
"username": {}
}
},
"settings": {
"authMethods": [
{
"config": {},
"type": "basic"
}
],
"rememberMeExp": 0,
"sessionExp": 0,
"sessionInactivityTimeout": 30,
"userSource": "default"
}
}

View File

@@ -0,0 +1,18 @@
{
"scope": "A",
"description": "Automatically generated Ignition Identity Provider which uses the User Source Profile named \"default\".",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {
"lastModification": {
"actor": "system-init",
"timestamp": "2026-07-16T15:30:29Z"
},
"uuid": "b2293888-bf60-47f3-8ee8-26de495c078a",
"lastModificationSignature": "6f0a3bc9d9be7660ac8cf0f13494d4805556d52f9c966a1540f3469ec1f7b9b7"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"about.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 607,
"lastModificationSignature": "3449ceb21db96dffee1170c58891f795be181263bff76121dd297f014cf8d590",
"height": 16
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"add2.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 201,
"lastModificationSignature": "1faea57ed9ee5df0251263686568405a928d18623e8ba0822521ac9e157a3fbe",
"height": 16
}
}

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"arrow_down_green.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 328,
"lastModificationSignature": "ec271579270bdd1342ab35ea16debeed804ee25e05ac760c6219af9e59d5fa8d",
"height": 16
}
}

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"arrow_left_green.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 321,
"lastModificationSignature": "4312e006a7b7f8d6f2af37d1b3f430917d9f647ccc5f029c02d68a1961d67b4c",
"height": 16
}
}

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"arrow_right_green.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 314,
"lastModificationSignature": "f641fa5d4854800d1fcd43ee244308f32ace9b35aa6c7a8f167fa7c13bac96c9",
"height": 16
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"arrow_up_green.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 299,
"lastModificationSignature": "1e7837f4727c17e34f73de731787b32b58b3d306c885678d206366c6e08a7f1c",
"height": 16
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"businessman.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 584,
"lastModificationSignature": "149e697b239db296783c6064a41bf8adbbafb10de761ecfc2d78f3735facf84d",
"height": 16
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"businessman2.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 641,
"lastModificationSignature": "a319f5ce9a7b681408f47c3876abcbc370e1845c09a6577e26a639e815c84ed5",
"height": 16
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"businessman_add.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 490,
"lastModificationSignature": "c864b723656b1cf7ffbdcee46ff1e5cb1fb98d64cbb39727fd043806f6e192f0",
"height": 16
}
}

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"businessman_delete.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 632,
"lastModificationSignature": "1208bba70a9078a953d8995a0cc2ee809b021a64d13797d81a9ad83aeb62b570",
"height": 16
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"businessmen.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 795,
"lastModificationSignature": "7d1455a7b474bfc54746622b0d6753d6af800f17e29f2455b1d1afb4a2c8953a",
"height": 16
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

View File

@@ -0,0 +1,20 @@
{
"scope": "A",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"calculator.png"
],
"attributes": {
"width": 16,
"format": "PNG",
"lastModification": {
"actor": "import",
"timestamp": "2026-07-16T15:30:46Z"
},
"size": 295,
"lastModificationSignature": "211e639c3684582c0ed1b932ad3397c74f291a7ca669e54b253ec43a970f968d",
"height": 16
}
}

Some files were not shown because too many files have changed in this diff Show More