Configuration
Categories:
Configuration
psLens reads a config.yaml file from the same directory as the binary. There is no external database server to set up. An embedded NATS data store saves persistent state (configuration history, report results, and alert state).
Configuration Synchronization
psLens synchronizes active configuration automatically between config.yaml and the embedded NATS KV store:
- Bare-Minimum Boot: The server can boot with zero configured database connections. Administrators can add database connections later directly through the Settings UI at
/settings. - Disk Edit Recognition: On boot, psLens checks modification timestamps. If
config.yamlis newer than the NATS KV snapshot, psLens syncs file changes into NATS KV automatically. - UI Auto Write-Back: Changes made via the Settings UI update NATS KV and automatically write back to
config.yamlon disk.
Password & Secret Security Options
psLens provides three secure methods for passing database and server credentials:
1Password Secret References (
op://...): Pass 1Password Secret URIs directly inconfig.yamlor JSON configurations:databases: - name: "PROD" username: "PSLENS_API" password: "op://Employee-Vault/PeopleSoft-Prod-API/password" smtp: host: "op://Employee-Vault/SMTP-Mailtrap/host" port: "op://Employee-Vault/SMTP-Mailtrap/port" username: "op://Employee-Vault/SMTP-Mailtrap/username" password: "op://Employee-Vault/SMTP-Mailtrap/password" fromName: "op://Employee-Vault/SMTP-Mailtrap/from_name" fromEmail: "op://Employee-Vault/SMTP-Mailtrap/from_email" auth: oidc: issuerUrl: "op://Employee-Vault/OIDC-Okta/issuer_url" clientId: "op://Employee-Vault/OIDC-Okta/client_id" clientSecret: "op://Employee-Vault/OIDC-Okta/client_secret" redirectUrl: "op://Employee-Vault/OIDC-Okta/redirect_url"Set
OP_SERVICE_ACCOUNT_TOKENin the environment. Secrets resolve in-memory at boot using the 1Password SDK and are never written back to disk or KV storage in plaintext.Master Key Encryption (
PSLENS_MASTER_KEY): SetPSLENS_MASTER_KEY(a 64-character hex AES-256 key). psLens saves passwords in NATS KV and YAML as encrypted strings (ENC[...]).Environment Variable Overrides: Override passwords dynamically via environment variables without editing files:
export PSLENS_DB_PROD_PASSWORD="YourPasswordHere"
Bare Minimum Configuration Example
To start psLens with zero pre-configured database connections, use the following minimal config.yaml:
server:
port: 8080
Full Configuration Examples
psLens supports configuration in either YAML (config.yaml) or JSON (config.json) format. The application detects the format automatically on boot.
YAML Configuration Example (config.yaml)
# Schema validation pointer (optional, for IDE support)
# yaml-language-server: $schema=http://localhost:8080/static/config-schema.json
server:
port: 8080
host: "0.0.0.0"
natsStoreDir: "./data/nats"
projectStoreDir: "./data/projects"
dmsStoreDir: "./data/dms"
traceStoreDir: "./data/traces"
appBaseURL: "http://localhost:8080"
recentlyViewed:
maxItems: 20
databases:
- name: "PROD"
description: "Production PeopleSoft HR"
baseURL: "https://psft.example.com:8000/PSIGW/RESTListeningConnector/PSFT_HR/CHG_PSLENS_SWSPQL/"
username: "PSLENS_API"
password: "your-api-password"
piaURL: "https://psft.example.com/psp/ps/"
timezone: "America/Chicago"
production: true
alerts:
enabled: true
intervalMinutes: 10
- name: "DEV"
description: "Development Environment"
baseURL: "https://psftdev.example.com:8000/PSIGW/RESTListeningConnector/PSFT_HR/CHG_PSLENS_SWSPQL/"
username: "PSLENS_API"
password: "dev-api-password"
timezone: "America/Chicago"
production: false
downtimes:
- name: "Nightly Downtime"
enabled: true
startTime: "22:00"
endTime: "06:00"
daysOfWeek: [1, 2, 3, 4, 5]
- name: "Weekend Maintenance"
enabled: true
startAt: "2026-07-04T00:00:00Z"
endAt: "2026-07-05T23:59:59Z"
alerts:
enabled: true
intervalMinutes: 5
checks:
long_running_processes:
enabled: true
thresholdMinutes: 20
anomalyMultiplier: 4.0
anomalyMinBaselineMinutes: 10
process_errors:
enabled: true
lookbackHours: 24
ib_operation_errors:
enabled: true
lookbackHours: 24
ib_pub_contract_errors:
enabled: true
lookbackHours: 24
ib_sub_contract_errors:
enabled: true
lookbackHours: 24
ib_operation_stalled:
enabled: true
thresholdMinutes: 30
ib_pub_contract_stalled:
enabled: true
thresholdMinutes: 30
ib_sub_contract_stalled:
enabled: true
thresholdMinutes: 30
genericSWSAlerts:
- id: "stale_users"
name: "Stale User Accounts"
enabled: true
severity: "warning"
alertOn: "row_found"
message: "Warning: Stale user accounts detected"
query:
records:
- recordName: "PSOPRDEFN"
sqlWhereClause: "LASTUPDDTTM < CAST('2026-01-01' AS TIMESTAMP) AND ACCTLOCK = 0"
rowLimit: 5
auth:
enabled: true
authorizedUsers:
- "admin@example.com"
- "auditor@example.com"
smtp:
host: "smtp.mailtrap.io"
port: "2525"
username: "smtp-user"
password: "smtp-password"
fromName: "psLens Alerts"
fromEmail: "alerts@pslens.example.com"
notifications:
subscriptions:
- id: "team-email"
enabled: true
alertTypes: ["*"]
databases: ["PROD"]
severityMin: "warning"
type: "email"
target: "psoft-alerts@example.com"
- id: "slack-webhook"
enabled: true
alertTypes: ["process_errors", "ib_operation_errors"]
databases: ["*"]
type: "webhook"
target: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
- id: "teams-webhook"
enabled: true
alertTypes: ["*"]
databases: ["*"]
type: "webhook"
target: "https://example.webhook.office.com/webhookb2/..."
- id: "google-chat-webhook"
enabled: true
alertTypes: ["*"]
databases: ["*"]
type: "webhook"
target: "https://chat.googleapis.com/v1/spaces/AAAA.../messages?key=...&token=..."
reports:
- id: "security-full-access-permlists"
enabled: true
dbNames: ["PROD"]
schedule:
interval: "daily"
timeOfDay: "02:00"
emailTarget: "psoft-alerts@example.com"
JSON Configuration Example (config.json)
{
"$schema": "http://localhost:8080/static/config-schema.json",
"server": {
"port": 8080,
"host": "0.0.0.0",
"natsStoreDir": "./data/nats",
"projectStoreDir": "./data/projects",
"dmsStoreDir": "./data/dms",
"traceStoreDir": "./data/traces",
"appBaseURL": "http://localhost:8080",
"recentlyViewed": {
"maxItems": 20
}
},
"databases": [
{
"name": "PROD",
"description": "Production PeopleSoft HR",
"baseURL": "https://psft.example.com:8000/PSIGW/RESTListeningConnector/PSFT_HR/CHG_PSLENS_SWSPQL/",
"username": "PSLENS_API",
"password": "your-api-password",
"piaURL": "https://psft.example.com/psp/ps/",
"timezone": "America/Chicago",
"production": true,
"alerts": {
"enabled": true,
"intervalMinutes": 10
}
},
{
"name": "DEV",
"description": "Development Environment",
"baseURL": "https://psftdev.example.com:8000/PSIGW/RESTListeningConnector/PSFT_HR/CHG_PSLENS_SWSPQL/",
"username": "PSLENS_API",
"password": "dev-api-password",
"timezone": "America/Chicago",
"production": false
}
],
"alerts": {
"enabled": true,
"intervalMinutes": 5,
"checks": {
"long_running_processes": {
"enabled": true,
"thresholdMinutes": 20,
"anomalyMultiplier": 4.0,
"anomalyMinBaselineMinutes": 10
},
"process_errors": {
"enabled": true,
"lookbackHours": 24
},
"ib_operation_errors": {
"enabled": true,
"lookbackHours": 24
},
"ib_pub_contract_errors": {
"enabled": true,
"lookbackHours": 24
},
"ib_sub_contract_errors": {
"enabled": true,
"lookbackHours": 24
},
"ib_operation_stalled": {
"enabled": true,
"thresholdMinutes": 30
},
"ib_pub_contract_stalled": {
"enabled": true,
"thresholdMinutes": 30
},
"ib_sub_contract_stalled": {
"enabled": true,
"thresholdMinutes": 30
}
},
"genericSWSAlerts": [
{
"id": "stale_users",
"name": "Stale User Accounts",
"enabled": true,
"severity": "warning",
"alertOn": "row_found",
"message": "Warning: Stale user accounts detected",
"query": {
"records": [
{
"recordName": "PSOPRDEFN",
"sqlWhereClause": "LASTUPDDTTM < CAST('2026-01-01' AS TIMESTAMP) and ACCTLOCK = 0"
}
],
"rowLimit": 5
}
}
]
},
"auth": {
"enabled": true,
"authorizedUsers": [
"admin@example.com",
"auditor@example.com"
]
},
"smtp": {
"host": "smtp.mailtrap.io",
"port": "2525",
"username": "smtp-user",
"password": "smtp-password",
"fromName": "psLens Alerts",
"fromEmail": "alerts@pslens.example.com"
},
"notifications": {
"subscriptions": [
{
"id": "team-email",
"enabled": true,
"alertTypes": ["*"],
"databases": ["PROD"],
"severityMin": "warning",
"type": "email",
"target": "psoft-alerts@example.com"
},
{
"id": "slack-webhook",
"enabled": true,
"alertTypes": ["process_errors", "ib_operation_errors"],
"databases": ["*"],
"type": "webhook",
"target": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
},
{
"id": "teams-webhook",
"enabled": true,
"alertTypes": ["*"],
"databases": ["*"],
"type": "webhook",
"target": "https://example.webhook.office.com/webhookb2/..."
},
{
"id": "google-chat-webhook",
"enabled": true,
"alertTypes": ["*"],
"databases": ["*"],
"type": "webhook",
"target": "https://chat.googleapis.com/v1/spaces/AAAA.../messages?key=...&token=..."
}
]
},
"reports": [
{
"id": "security-full-access-permlists",
"enabled": true,
"dbNames": ["PROD"],
"schedule": {
"interval": "daily",
"timeOfDay": "02:00"
},
"emailTarget": "psoft-alerts@example.com"
}
]
}
Server Settings
The server section controls how psLens listens for incoming connections and where it stores data.
| Setting | Default | Description |
|---|---|---|
port | 8080 | TCP port psLens listens on |
host | 0.0.0.0 | Network interface to bind (use 127.0.0.1 to restrict to localhost) |
natsStoreDir | ./data/nats | Directory for persistent NATS data (report results, alert history) |
projectStoreDir | ./data/projects | Directory for uploaded PeopleSoft project XML definitions |
dmsStoreDir | ./data/dms | Directory for imported Data Mover (DMS) script libraries |
traceStoreDir | ./data/traces | Directory for uploaded PeopleSoft trace files (.tracesql, .trc, .aet) |
outageRetentionDays | 90 | Retention period in days for historical downtime and outage events stored in NATS JetStream. |
Tip: Storage directories (
natsStoreDir,traceStoreDir, etc.) can also be configured via environment variables (PSLENS_TRACE_STORE_DIR,PSLENS_PROJECT_STORE_DIR, etc.) and should be placed on persistent storage.
Database Connections
You can configure one or more PeopleSoft databases under the databases list. psLens monitors the health of each connection and shows status on the dashboard.
| Setting | Required | Description |
|---|---|---|
name | Yes | Short identifier shown in the UI (e.g., PROD, DEV) |
description | Yes | Human-readable label for the database |
baseURL | Yes | Full URL to the SWS psoftQL endpoint, including the service name |
username | Yes | PeopleSoft operator ID for API authentication |
password | Yes | Password for the operator ID |
piaURL | No | Base URL for PeopleSoft Internet Architecture (used for deep links to PeopleSoft pages, if supported) |
timezone | No | IANA timezone name for the database server (e.g., America/Chicago). Defaults to UTC if not set. Used to interpret timestamps correctly. |
downtimes | No | List of scheduled downtime windows to suppress alerts and monitoring. |
notifications | No | Database-specific notification delivery settings (bypasses global subscriptions). |
Scheduled Downtimes
Downtimes allow silencing alerts and pausing connection health checks for non-production environments that go offline regularly (e.g., overnight or on weekends).
Each entry in the downtimes list supports the following settings:
| Setting | Required | Description |
|---|---|---|
name | Yes | Identifier for the downtime window. |
enabled | Yes | Whether the downtime rule is active. |
startTime | No | Start time of day in HH:MM format (e.g., 22:00). Set together with endTime. |
endTime | No | End time of day in HH:MM format (e.g., 06:00). An end time earlier than the start crosses midnight. 24:00 means end of day, so an all-day window is 00:00–24:00. |
daysOfWeek | No | Array of integers for days of week. 0 is Sunday, 1 is Monday, …, 6 is Saturday. Omit to apply every day. An overnight window belongs to the day it starts. |
startAt | No | Specific start timestamp in RFC3339 format (e.g., 2026-07-04T00:00:00Z) for one-off maintenance. |
endAt | No | Specific end timestamp in RFC3339 format (e.g., 2026-07-05T23:59:59Z) for one-off maintenance. |
Values for startTime and endTime use wall-clock times in the connection timezone (UTC if unset). psLens checks rules when saving configuration. A rule must define a recurring window (startTime and endTime) or a one-off range (startAt and endAt).
During scheduled downtime, the connection manager sets database status to Downtime on the dashboard. psLens skips background alert checks and suppresses notification dispatches. The database does not count against overall health. When the window ends, psLens checks the connection immediately. It treats the first failed check as an outage. Size windows to cover system boot time.
A weekend window that spans from Saturday evening to Monday morning requires two rules. An overnight window belongs to its start day:
downtimes:
- name: "Weekend nights"
enabled: true
startTime: "22:00"
endTime: "06:00"
daysOfWeek: [6, 0] # Sat night -> Sun morning, Sun night -> Mon morning
- name: "Sunday all day"
enabled: true
startTime: "00:00"
endTime: "24:00"
daysOfWeek: [0]
The baseURL Format
The baseURL is the Integration Broker REST endpoint for the SWS service. It follows this pattern:
https://{igw-host}:{port}/PSIGW/RESTListeningConnector/{database-name}/CHG_PSLENS_SWSPQL/
You must include the trailing slash.
Environment Variable Overrides
Sensitive settings like passwords can be overridden with environment variables to avoid storing them in config.yaml. The override format is:
PSLENS_DB_{NAME}_{FIELD}
Where {NAME} matches the name field of the database in config.yaml.
For Fly.io and Docker container compatibility, non-alphanumeric characters (such as dashes - or dots .) in database names are automatically converted to underscores (_) and uppercased.
For example, for a database named COOL-DB-FOR-DEV, you can use:
export PSLENS_DB_COOL_DB_FOR_DEV_PASSWORD="my-secure-password"
The raw name PSLENS_DB_COOL-DB-FOR-DEV_PASSWORD remains supported for backward compatibility where supported by your shell.
1Password Secret References
You can place 1Password secret references (op://...) directly in config.yaml or through the Settings UI. Supported fields include:
- Database Connections:
baseURL,username,password,piaURL - Database Notifications:
notifications.emailTarget,notifications.webhookTarget - Database WebLib Health Checks:
alerts.checks[].weblibTestTargets[].url,username,password - SMTP Mailer:
smtp.host,smtp.port,smtp.username,smtp.password,smtp.fromName,smtp.fromEmail - Authentication (OIDC):
auth.oidc.issuerUrl,auth.oidc.clientId,auth.oidc.clientSecret,auth.oidc.redirectUrl - Notifications & Subscriptions:
notifications.email_lists[].emails,notifications.webhooks[].url,notifications.subscriptions[].target
databases:
- name: "PROD"
baseURL: "op://VaultName/ItemName/base_url"
username: "PSLENS_API"
password: "op://VaultName/ItemName/password"
To resolve 1Password secret references at boot, set a 1Password Service Account token in the environment:
export OP_SERVICE_ACCOUNT_TOKEN="op_service_account_token_here"
When you provide OP_SERVICE_ACCOUNT_TOKEN (or PSLENS_OP_SERVICE_ACCOUNT_TOKEN), psLens resolves all op:// references on boot using the 1Password SDK. Without this variable, psLens skips 1Password resolution.
Database-Specific Notifications
By default, global subscription rules route alert notifications for all databases (see Notifications & Webhooks Settings).
You can configure database-specific notifications under the notifications property of a database entry. This setting acts as an override. Database-level targets receive all alerts and resolutions for that database, bypassing global subscriptions.
Each entry in the notifications block supports the following settings:
| Setting | Type | Description |
|---|---|---|
emailEnabled | Boolean | Activates email notifications for this database. |
emailTarget | String | Comma-separated list of recipient email addresses. |
webhookEnabled | Boolean | Activates webhook notifications for this database. |
webhookTarget | String | Webhook ID or destination URL (Slack, MS Teams, Google Chat, or a generic endpoint). |
Example database connection configuration with inline notifications:
databases:
- name: "PROD"
description: "Production Environment"
baseURL: "https://psft.example.com:8000/PSIGW/RESTListeningConnector/PSFT_HR/CHG_PSLENS_SWSPQL/"
username: "PSLENS_API"
password: "securepassword"
notifications:
emailEnabled: true
emailTarget: "prod-alerts@example.com"
webhookEnabled: true
webhookTarget: "https://hooks.slack.com/services/..."
Alerts Configuration
The alerts section controls the background alert checking system. See the Alerts section for details on what each alert detects.
Top-Level Alert Settings
| Setting | Default | Description |
|---|---|---|
enabled | false | Whether to run background alert checks |
intervalMinutes | 5 | How often (in minutes) to run all alert checks |
genericSWSAlerts | [] | List of queryable SWS alerts. See Generic SWS Alerts for details. |
Alert Check Settings
Each alert type under checks supports some or all of the following settings:
| Setting | Description |
|---|---|
enabled | Whether this check is active |
thresholdMinutes | For stalled/long-running checks: how many minutes before flagging (default varies by check). For long_running_processes, this is the fallback static threshold. |
lookbackHours | For error checks: how many hours back to look for failures (default varies by check) |
excludeProcesses | List of process names to skip (for process-related checks) |
excludeOperations | List of IB operation names to skip (for Integration Broker checks) |
anomalyMultiplier | Multiplier applied to the rolling median duration to calculate the dynamic threshold (default: 4.0) |
anomalyMinBaselineMinutes | Minimum baseline duration in minutes. psLens caps dynamic thresholds to at least this value to prevent false alerts on very fast processes (default: 10) |
Available Alert Checks
| Check Key | Name | Description |
|---|---|---|
long_running_processes | Long-Running Processes | Flags processes running longer than their rolling median-based expected runtime (or thresholdMinutes fallback) |
process_errors | Process Errors | Finds processes that failed within lookbackHours (default: 24 hours) |
ib_operation_errors | IB Operation Errors | Finds async IB operations in Error or Timeout status within lookbackHours (default: 24 hours) |
ib_pub_contract_errors | IB Publication Contract Errors | Finds pub contracts in Error or Timeout status within lookbackHours (default: 24 hours) |
ib_sub_contract_errors | IB Subscription Contract Errors | Finds sub contracts in Error or Timeout status within lookbackHours (default: 24 hours) |
ib_operation_stalled | IB Operations Stalled | Finds async IB operations stuck in New or Working status longer than thresholdMinutes (default: 30 min) |
ib_pub_contract_stalled | IB Publication Contracts Stalled | Finds pub contracts stuck in New or Working status longer than thresholdMinutes (default: 30 min) |
ib_sub_contract_stalled | IB Subscription Contracts Stalled | Finds sub contracts stuck in New or Working status longer than thresholdMinutes (default: 30 min) |
locked_oprid_processes | Locked OPRID Scheduled Processes | Finds queued or scheduled processes whose submitting OPRID has a locked account |
backlogged_processes | Backlogged Processes | Detects processes currently stuck in a Queued or Blocked state longer than thresholdMinutes (default: 30 min) |
queue_latency | Queue Latency | Detects processes that experienced a start delay (BEGINDTTM - RUNDTTM) greater than thresholdMinutes (default: 15 min) |
failed_logins | Failed Logins | Detects users with excessive failed login attempts in PSPTLOGINAUDIT (defaults to > thresholdCount of 5) |
process_run_check | Process Run Check | Monitors configured critical processes and alerts when they haven’t run successfully within their configured time window |
ib_operation_volume | Abnormal IB Operation Volume | Detects when IB operation instance volume exceeds the historical average by a percentage specified in thresholdCount (default: 50) |
ib_pub_contract_volume | Abnormal IB Pub Contract Volume | Detects when IB publication contract volume exceeds the historical average by a percentage specified in thresholdCount (default: 50) |
ib_sub_contract_volume | Abnormal IB Sub Contract Volume | Detects when IB subscription contract volume exceeds the historical average by a percentage specified in thresholdCount (default: 50) |
ib_sync_exceptions | IB Sync Operation Exceptions | Detects synchronous service operations with errors in PSIBLOGHDR within lookbackHours (default: 24 hours). Disabled by default. |
no_process_completed | No Process Completed | Fires when no process has successfully completed within the lookbackHours (default: 1 hour) |
ib_down | Integration Broker Down | Alerts when SWS REST endpoint connection failures indicate the Integration Broker is down |
weblib_down | Web Server / WebLib Down | Alerts when PeopleSoft Web Server is down or configured WebLib URLs fail to respond |
ib_no_active_domain | IB No Active Domain | Alerts when there is no active domain found in PSAPMSGDOMSTAT |
ib_dispatcher_down | IB Dispatcher Down | Alerts when an Integration Broker dispatcher process is inactive or has not updated status within thresholdMinutes (default: 10 min) |
ib_nodes_down | IB Nodes Down | Alerts when there are entries in PSNODESDOWN indicating message nodes are down |
Authentication Settings
The auth section configures native authentication (email-based magic link or native OpenID Connect SSO). psLens enables authentication by default. To disable authentication, set enabled: false explicitly in config.yaml. Authentication settings are file-authoritative. You cannot change or turn off authentication from the web interface.
| Setting | Default | Description |
|---|---|---|
enabled | true | Defaults to true. To disable, set to false explicitly in config.yaml. |
mode | magic_link | Authentication mode: magic_link or oidc. |
authorizedUsers | [] | Whitelist of email addresses allowed to log in (case-insensitive). |
oidc.issuerUrl | - | OpenID Connect Issuer URL (supports op:// 1Password references). |
oidc.clientId | - | OIDC Application Client ID (supports op:// 1Password references). |
oidc.clientSecret | - | OIDC Application Client Secret (supports op:// 1Password references). |
oidc.redirectUrl | - | Optional custom OAuth2 callback URL (supports op:// 1Password references). |
oidc.scopes | ["openid", "profile", "email"] | OIDC authorization scopes requested from the Identity Provider. |
oidc.allowedGroups | [] | Optional list of required group claims to restrict access. |
oidc.groupClaim | groups | Claim key in the ID token used for group membership verification. |
ipAllowlist.enabled | false | Enable IP allowlist enforcement. Fails closed (denies all) if list is empty. |
ipAllowlist.allowedCIDRs | [] | List of allowed CIDR blocks or IP addresses (e.g. ["10.0.0.0/8", "192.168.1.50"]). |
SMTP Settings
Configure email server settings under Settings → Notifications (Email Server card). Changes apply to alert and report emails immediately. Login (magic link) emails use new settings after the next server restart. A blank password on save keeps the stored password.
The smtp block in config.yaml seeds the email server on first boot only. After initial boot, settings saved in the UI remain authoritative. PSLENS_SMTP_* environment variables override both sources and make the UI card read-only.
| Setting | Default | Description |
|---|---|---|
host | - | SMTP server hostname/IP (supports op:// 1Password references) |
port | - | SMTP port (e.g. 25, 465, 587, 2525, supports op:// references) |
username | - | Username for SMTP auth (supports op:// 1Password references) |
password | - | Password for SMTP auth (supports op:// 1Password references) |
fromName | psLens | Sender name shown in emails (supports op:// 1Password references) |
fromEmail | - | Sender email address for SMTP. Required: no email is sent without it (supports op:// 1Password references) |
Test outbound email on the same card: enter a recipient address under Send Test Email and click Send Test. psLens records the test result in Alert Delivery History.
Notifications & Webhooks Settings
Notification rules determine where psLens dispatches alert messages. Manage rules in the app under Settings → Notifications. There, you configure and test email distribution lists, webhook destinations, and subscription routing rules. For step-by-step instructions on creating webhooks in Google Chat, Slack, and Microsoft Teams, see Webhook Integrations.
Email Distribution Lists (notifications.email_lists)
Predefined recipient lists referenced by notifications and reports:
notifications:
email_lists:
ops_team:
name: "Operations Team"
emails: "ops@company.com, pager@company.com"
Webhooks (notifications.webhooks)
Predefined incoming webhook URLs for Slack, Microsoft Teams Workflows (Adaptive Cards), Google Chat (cardsV2), or custom JSON receivers:
notifications:
webhooks:
slack_alerts:
name: "Slack Alert Channel"
url: "https://hooks.slack.com/services/..."
teams_ops:
name: "Teams Operations Channel"
url: "https://default...powerautomate.../invoke"
gchat_ops:
name: "Google Chat Space"
url: "https://chat.googleapis.com/v1/spaces/.../messages?key=...&token=..."
To create a Google Chat incoming webhook URL, open the target Space in Google Chat, click the Space name header → Apps & integrations → + Add webhooks, save the webhook, and copy the https://chat.googleapis.com/v1/spaces/.../messages?key=...&token=... link. See Webhook Integrations for full setup instructions.
Subscriptions (notifications.subscriptions)
Routing subscriptions matching fired alerts and dispatching them to email or webhook targets:
| Property | Type | Description |
|---|---|---|
id | String | Unique identifier for the subscription |
enabled | Boolean | Activates or silences the subscription |
alertTypes | List of Strings | Alert check keys to match (e.g. ["*"] for all, or ["process_errors"]) |
databases | List of Strings | Database names to match (e.g. ["*"] or ["PROD"]) |
severityMin | String | Minimum alert severity ("info", "warning", "critical") |
type | String | Dispatch protocol: "email" or "webhook" |
target | String | Target destination: email address, distribution list key, or webhook destination URL / key |
Note: psLens automatically detects Slack, MS Teams Adaptive Card, and Google Chat webhook URLs and formats native payloads accordingly.
Reports Scheduling Settings
The reports section allows you to define static scheduling configs and completion notifications directly in the configuration file.
Report Properties
Under reports, define a list of scheduled report objects:
| Property | Type | Description |
|---|---|---|
id | String | The unique report definition ID (e.g. security-full-access-permlists) |
enabled | Boolean | Enables or disables the scheduled execution of this report (defaults to true) |
dbNames | List of Strings | Database names to target (e.g., ["PROD"]). If omitted, targets all active databases. |
schedule | Object | Timing recurrence properties (see below) |
emailTarget | String | Optional email address to send report completion notifications to |
webhookTarget | String | Optional Slack, MS Teams, Google Chat, or JSON webhook endpoint to send notifications to |
Schedule Recurrence Properties
Under reports.schedule, define when the job should run:
| Property | Type | Description |
|---|---|---|
interval | String | Recurrence frequency: "daily", "weekly", or "monthly" |
timeOfDay | String | 24-hour format execution time ("HH:MM", e.g., "02:00") in server local time |
dayOfWeek | Integer | Optional. Day of the week for weekly runs (0 for Sunday, 1 for Monday, …, 6 for Saturday) |
dayOfMonth | Integer | Optional. Day of the month for monthly runs (1 to 28) |
JSON Schema Validation
To enable autocompletion, tooltips, and real-time schema validation within your IDE (such as VS Code), use the built-in JSON schema:
Option A: Live URL (Online)
If your psLens server is running locally (e.g., on port 8080), you can add the $schema parameter to the top of your JSON config file:
{
"$schema": "http://localhost:8080/static/config-schema.json",
"server": {
"port": 8080
}
}
Option B: Local File Reference (Offline)
To configure your workspace offline, reference the schema file directly. In VS Code, add this to your .vscode/settings.json:
{
"json.schemas": [
{
"fileMatch": ["config.json"],
"url": "./static/config-schema.json"
}
],
"yaml.schemas": {
"./static/config-schema.json": ["config.yaml"]
}
}
Securing psLens
For production deployments, you should restrict access to the psLens interface.
Recommended Security Controls
- Enable Built-In Magic Link Auth:
Turn on
auth.enabledand configure SMTP credentials andauthorizedUsersto require code validation on login. - Setup a Master Key (
PSLENS_MASTER_KEY): Provide a 32-byte (64 hex characters) key in thePSLENS_MASTER_KEYenvironment variable. All database and SMTP passwords entered in the UI or configuration are then encrypted at rest using AES-256-GCM. - Reverse Proxy / VPN:
Place psLens behind a reverse proxy (e.g., Cloudflare Access, oauth2-proxy, nginx, Tailscale) to delegate authentication to your company’s Identity Provider (SAML/OIDC). When using an external SSO proxy, you can keep
auth.enableddisabled and restrict the psLens binary to bind only on127.0.0.1or internal networks.
Warning: Never expose psLens to the public internet without authentication. Enable built-in magic-link auth or place an authenticated reverse proxy in front of psLens. Unprotected instances expose read access to PeopleSoft metadata.
Active Configuration and Hot-Reloading
psLens keeps its settings in two places:
- Active configuration (embedded key-value store): Web interface edits save here and take effect immediately without server restarts. psLens records each change as a numbered revision under Settings → Change History. You can view or restore any revision.
config.yamlon disk: the bootstrap file that seeds the active configuration on first boot. Saved changes are also written back to it as a backup on the persistent storage volume.
Configuration Seeding
On initial boot, or when you set the environment variable PSLENS_FORCE_SEED_CONFIG=true, psLens seeds active configuration from config.yaml.
If the active configuration drifts from config.yaml, the Settings → Advanced page shows a “Settings differ from the config.yaml file on disk” notice. To resolve it:
- Click Load settings from config.yaml on the Advanced page. This overwrites active configuration with file contents and discards changes made in the UI.
- If the file path is writable, click Overwrite config.yaml on disk to write active configuration to disk. On ephemeral deployment models without persistent volumes, restarting or re-deploying the container discards local file changes.
- Alternatively, copy the Active Configuration YAML from the Advanced page into your
config.yamlfile to bring the disk file in sync.
Secret Key Management (Encryption at Rest)
When you configure the PSLENS_MASTER_KEY environment variable with a 32-byte hex-encoded key, psLens encrypts database and SMTP passwords at rest. Without this master key, psLens saves passwords in plaintext.
Rotating the Master Key
To rotate the cryptographic key used for credential encryption:
- Enter a new 32-byte hex key in the Rotate Encryption Key field.
- Click Rotate Master Key. The server decrypts all stored credentials using the old key and re-encrypts them with the new key in NATS KV.
- Update the
PSLENS_MASTER_KEYenvironment variable in your deployment configuration (e.g., Fly.io secrets or.envfile) to match the new key before restarting the container. If the container restarts with a mismatched key, it cannot decrypt the configuration.