Data Handling & Logging

What psLens stores, what it does not, how data is encrypted at rest and in transit, and what gets logged for audit.

This page is for compliance reviewers and DPOs who need a precise answer to “what data does psLens hold, where, and for how long?”, and for security teams checking encryption and audit-trail posture.

For PII handling, jump to Personal Data (PII).


1. What psLens Stores

psLens persists three categories of data, all inside the customer’s own dedicated instance. There is no shared multi-tenant backend.

WhereWhatRetentionNotes
/data/nats (NATS JetStream KV)Alert historyRolling window (configurable; short by default)Alerts are about current problems. History is for trend review, not long-term audit.
/data/natsReport output (Markdown)90 daysSo you can revisit past audit findings; configurable
/data/natsRecently-viewed objects per userSession-scopedNavigation convenience; not an audit log
/data/natsEncrypted DB / SWS credentialsUntil deletedAES-256-GCM, key from PSLENS_MASTER_KEY env var
/data/natsAuth sessions (if auth.enabled)Up to 1 year TTLSee Authentication & Access
/data/projectsUploaded PS project archives (.zip)Until deletedUsed by Project Compare; you control the upload set
/app/config.yamlConfiguration (DB names, SWS endpoints, optional credentials)Until you change itBind-mounted from your filesystem; secrets preferably via env vars

That is the complete persistent footprint. Everything else (query results, page renders, search hits) is generated on demand and not written to disk.


2. What psLens Does NOT Store

  • PeopleSoft business data. Employee records, payroll, financial transactions, HR data, customer records, journals, vouchers. None of it. Reports summarize at runtime and discard the raw rows.
  • Database passwords in cleartext (when PSLENS_MASTER_KEY is set).
  • End-user passwords. psLens uses magic-link or reverse-proxy SSO; there are no user passwords to store.
  • Logs on disk. Logs go to stderr; your container runtime decides what to do with them.
  • Telemetry, analytics, or usage data shipped back to Cedar Hills Group. psLens does not phone home.
  • Client-side cached data. Nothing is cached in the browser. No writes to LocalStorage, SessionStorage, or IndexedDB; close the tab and there is nothing left.

3. Personal Data (PII)

The answer is more nuanced than “no PII”.

psLens does not store PeopleSoft user PII. No persistent table or KV entry contains employee or operator records.

psLens does process PeopleSoft user PII at request time. When a user opens a search for Users, Operator IDs, or related security objects, psLens queries PeopleSoft, renders fields like OPRID, OPRDEFNDESC, EMAILID, and EMPLID in the browser, and discards the rows after the response. The data passes through psLens memory; it is not written to NATS, disk, or any log.

What this means for GDPR / CCPA / similar:

  • psLens acts as a processor of this data while a query is in flight.
  • The controller is the PeopleSoft owner (the customer).
  • A DPA is available on request. See Compliance & Vendor.
  • Subject access / erasure requests are handled at the PeopleSoft source of record. psLens has nothing to delete because it has nothing persisted.

If your jurisdiction or policy requires that even transient processing be scoped, the AuthorizedUsers allowlist and the SWS table whitelist give you two layers of control over who can trigger such a query at all.


4. Encryption

In transit

HopProtocolNotes
Browser → psLens UIHTTPSVia your TLS pattern. See Deployment Options (6 options compared).
psLens → SWS endpointHTTPSBasic-auth credentials never on the wire in clear
psLens → SMTP (if magic-link auth)SMTPS / STARTTLSConfigurable per your SMTP provider

The SWS endpoint URL is HTTPS in every supported deployment. If you have a network where the PS server is reachable only over HTTP, raise it on the demo call. Running psLens over plaintext to PS is not a supported posture.

At rest

ItemEncryptionKey source
SWS / DB credentials in NATS KVAES-256-GCMPSLENS_MASTER_KEY env var (32 bytes, hex-encoded)
Auth sessions in NATS KVOpaque session IDs only; no secret material at restn/a
Report outputNot encrypted (plain Markdown)Stored on the customer-controlled volume
Alert historyNot encrypted (alert metadata)Stored on the customer-controlled volume
Project archive uploadsNot encrypted at application layerDisk-level encryption (LUKS, fly.io volumes, EBS) is the recommended boundary

Master key management:

  • Required (and enforced at startup) when PSLENS_ENV=production.
  • Stored as a 64-char hex string (32 raw bytes) in the PSLENS_MASTER_KEY env var. On fly.io: fly secrets set PSLENS_MASTER_KEY=.... In Docker Compose: .env file with 0600 permissions, or an external secret manager.
  • Back it up out of band. Losing the master key means encrypted DB credentials in NATS KV become unreadable; you’d need to re-enter them.
  • Self-service rotation. Generate a new key and trigger rotation directly from the Settings UI (Advanced page). The server decrypts all stored credentials using the old key and re-encrypts them with the new key in NATS KV. The operator must update the PSLENS_MASTER_KEY environment variable in the deployment configuration to match the new key before the container restarts.

5. Audit Logging

What psLens logs today

EventWhere it goesIncludes
Every HTTP requeststderr (structured slog)X-Request-Id, path, method, status, duration, authenticated user email (if auth.enabled)
Application errorsstderr (structured slog)Stack-relevant context, request ID for correlation
Startup bannerstderrVersion, commit SHA, build timestamp
Alert checker runsstderr + NATS KV (alert history)Which checker, what it found

The request ID flows through every log line tied to a request, so you can correlate a UI action to its server-side handler chain.

Logs are written to stderr only. psLens does not write logs to disk. Your container runtime decides what happens next: typically piped to your Docker logging driver, your systemd journal, your fly.io log stream, or your K8s log shipper. Send them to your SIEM via the same standard mechanism you use for any container workload.

Where the user-action audit actually lives today

Because psLens is read-only, the question “who looked at what PS data, when” has its authoritative answer on the PeopleSoft side. The SWS framework logs every query it accepts, including the OPRID of the SWS service account, the SQL it ran, and the timestamp. That is the audit trail that matters for “did someone see employee X’s record”.

What psLens contributes:

  • The HTTP request log (above) ties an authenticated psLens user to a specific page hit, and the page hit corresponds to a known set of SWS queries.
  • Correlation across the two logs uses the request ID on the psLens side and the timestamp + query pattern on the SWS side.

The gap and the roadmap

Today, psLens does not write a structured per-user “action” audit log. For example, {user: alice, action: viewed, object: PSRECDEFN PS_VOUCHER, at: 2026-05-21T14:32Z}. The HTTP request log is close to that but is operational logging, not an audit artifact.

Roadmap: add a first-class user-action audit log written to a NATS KV bucket with configurable retention, exportable to your SIEM. Targeted to land alongside native SSO. No committed date.

If a customer needs a richer audit story today, the recommended interim is: enable auth.enabled, ship the HTTP request log to your SIEM, and correlate with the SWS-side audit. Cedar Hills Group can help with the correlation queries.

Retention

psLens retains structured logs only in your container runtime’s log stream. Retention is whatever you configure there. No psLens-managed log retention policy exists; we deliberately stay out of that decision so it aligns with your existing log-retention SLAs.


6. What Reviewers Usually Ask

“Where is the data physically?” In your dedicated psLens instance. Managed deployments live in the fly.io region you choose at provisioning. Self-hosted: wherever you run the container. There is no shared backend.

“Can you delete all data for a customer on request?” Yes, by removing the deployment. Because all customer-specific state lives in the per-customer container’s /data volume, deletion is fly apps destroy or docker compose down --volumes. There is no other location to scrub.

“Do you encrypt the entire volume?” Application-level encryption covers credentials. Volume-level encryption is the customer’s choice. On fly.io, volumes are encrypted at rest by default; on your own infrastructure, use LUKS / EBS encryption / equivalent.

“Do you have an SBOM?” Available on request for any tagged build. See Code & Supply Chain.