This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Security & Trust

How psLens protects your PeopleSoft environment: read-only by design, table whitelist, dedicated instance per client, no direct database access.

psLens gives your team a window into PeopleSoft metadata. It cannot write to your database, it cannot query outside a whitelist you approve, and your instance does not share anything with anyone else’s.

The Short Version

  • Read-only by design. psLens never writes to PeopleSoft. There is no code path that issues INSERT, UPDATE, or DELETE against your environment.
  • No direct database credentials required. psLens connects to PeopleSoft through the SWS framework, which exposes a bounded REST API. Your database passwords stay on your side.
  • Query surface is whitelisted. psLens can only query PeopleTools metadata tables that are explicitly allowed. Anything off-list is rejected before it reaches PeopleSoft.
  • Dedicated instance per client. Each customer gets their own isolated deployment. No shared tenancy, no shared database, no cross-customer blast radius.
  • Your PeopleSoft business data stays in PeopleSoft. psLens stores alert history and report output only, nothing else.
  • Nothing is cached in the browser. Pages render server-side and stream over SSE. psLens writes nothing to LocalStorage, SessionStorage, or IndexedDB; closing the tab clears everything.

For the high-level picture of how psLens is deployed and how it talks to PeopleSoft, see the Architecture Overview. This page focuses on the security implications of that design.

How Queries Reach PeopleSoft

%%{init: {"flowchart": {"htmlLabels": true, "padding": 16, "nodeSpacing": 50, "rankSpacing": 60}}}%%
flowchart TD
    APP["psLens app<br/>(dedicated instance per customer)"]
    SWS["SWS framework<br/>(installed in your PeopleSoft environment)"]
    DB[("PeopleSoft database<br/>(read-only)")]

    APP -- "HTTPS + basic auth<br/>(token in config.yaml or env var)" --> SWS
    SWS -- "psoftQL, scoped to<br/>whitelisted tables" --> DB

    classDef ps fill:#e8f4fd,stroke:#0d6efd,stroke-width:2px,color:#000
    classDef ext fill:#fff5e6,stroke:#fd7e14,stroke-width:2px,color:#000
    class APP ext
    class SWS,DB ps

Every query psLens issues flows through this path. There is no second channel. If the SWS framework is not installed, psLens cannot see anything.

Read-Only by Design

psLens reads metadata. It does not change anything in PeopleSoft, and it has no code path that could:

  • No administrative actions. Reports, alerts, and metadata browsing are all read operations.
  • No PeopleCode execution. psLens inspects configuration; it does not run it.
  • No project migration, no security grants, no user creation.

If you want to change something you see in psLens, you still do that in App Designer, PIA, or your existing change-management process.

Query Surface: The Table Whitelist

The SWS framework only responds to queries against tables that are explicitly whitelisted. psLens ships knowing which PeopleTools metadata tables it needs: PSRECDEFN, PSPNLDEFN, PSCLASSDEFN, PSAUTHITEM, process scheduler tables, Integration Broker tables, and similar (a known, published list).

A query that references any table outside the whitelist is rejected by SWS before it touches the database. This is enforced on your side of the connection, not the psLens side. Even if psLens were misconfigured, it could not reach into payroll, HR, financials, or any other transactional data.

When you add psLens to an environment, you see the whitelist and approve it. You can review or narrow it at any time.

Credential Handling

  • The SWS endpoint uses HTTP basic auth over HTTPS.
  • The auth token is stored in psLens config.yaml or injected through environment variables at deployment time.
  • No PeopleSoft database username or password is ever needed by psLens.
  • No single-sign-on tokens, session cookies, or end-user credentials are stored.

Rotating the SWS auth token is straightforward: rotate on the PeopleSoft side, update the psLens config or env var, restart the instance.

Deployment Isolation

Every psLens customer gets a dedicated deployment:

  • One instance per customer. No shared app, no shared database, no shared filesystem.
  • Hosted on fly.io by default, with deployment options to match your security requirements.
  • Your data does not traverse a shared service. There is no psLens SaaS multi-tenant backend.
  • If you prefer to host psLens yourself in your own cloud account or on-prem, that is supported — see installation for bare-metal and Docker options, including air-gapped environments.

What psLens Stores

psLens only persists two categories of data, and both stay inside your dedicated instance:

  • Alert history. A rolling record of alerts that fired, for trend review. Retention is configurable; defaults to a short window because alerts are meant to surface current issues.
  • Report output. The Markdown output of reports you have run, kept for 90 days so you can revisit audit findings or compare runs. See reports.

psLens does not copy PeopleSoft business data (employee records, financial transactions, HR data) into its own storage. Reports pull what they need at run time and summarize it; browsing and search fetch metadata on demand and display it.

What psLens Does NOT Do

  • It does not write to PeopleSoft.
  • It does not require a direct database connection.
  • It does not store PeopleSoft business data outside of alert and report output.
  • It does not share a database or application instance across customers.
  • It does not phone home. Your deployment talks to your PeopleSoft environment; it does not report back to Cedar Hills Group.

Going Deeper

This page is the short version. If you’re preparing a vendor security review or filling out a SIG / CAIQ, these pages cover the topics your reviewers will ask about: current state, gaps, and roadmap, stated plainly.

If a quick Q&A is all you need, the FAQ has one-paragraph answers cross-linked to the deeper pages above.

Questions Before a Demo?

If you have specific security or compliance questions (data residency, SWS role permissions on your PeopleSoft side, how to integrate with your existing SSO for the psLens login layer) raise them on the demo call or email chris.malek@cedarhillsgroup.com and we will answer in writing before you commit to anything.

1 - What SWS Installs in PeopleSoft

The objects, roles, and Integration Broker setup the SWS framework adds to a PeopleSoft environment. Written for the admin, DBA, or security reviewer who has to approve the install.

The SWS (Secure Web Services) framework is the PeopleSoft-side component psLens queries through. This page lists what installing it actually changes in your environment, so the person approving the change can see the full footprint before anything is migrated. The authoritative installation guide lives at sws.books.cedarhillsgroup.com; this page is the summary for a security review.

The Install in One Paragraph

SWS is delivered as a standard App Designer project. You import it into a development environment first, test it there, and migrate it to TEST and PROD through your normal change-management path, the same way you move any other project. There is no installer, no agent, and no software on the database server. Plan for under an hour of PeopleSoft admin time for the first environment.

What the Project Contains

Roughly 100 PeopleSoft objects, all namespaced with the CHG_ prefix (C_ for records):

  • 9 records for configuration and logging, including the whitelist tables described below
  • 32 fields supporting those records
  • 4 pages for administration and testing
  • 6 application packages containing the framework’s PeopleCode
  • 2 service operations: CHG_SWS_GET and CHG_SWS_PSOFTQL_POST
  • 2 roles: CHG_SWS_ADMIN (setup pages) and CHG_SWS_USER (API access)

The full object manifest is in the SWS installation docs. The project ships with sample data for testing; the SWS docs are explicit that sample data is not meant for production systems.

Security Objects and the Service Account

psLens connects as a PeopleSoft operator you create for it (for example PSLENS_API). That account:

  • holds the CHG_SWS_USER role, which grants access to the API and nothing else
  • authenticates to the service operations with HTTP basic auth over HTTPS
  • is an ordinary PeopleSoft account, so your existing controls apply: lock it in PSOPRDEFN and all psLens access stops immediately

No new database users are created. Nothing connects to the database directly; every query runs through the application server like any other Integration Broker request.

The Whitelist

SWS only answers queries against records listed in PS_C_SWS_REC_WL, scoped to the permission list of the calling API user. A query that references anything off-list is rejected before it reaches the database.

psLens needs roughly 130 PeopleTools metadata records whitelisted. The list is published in two places: the Reference page describes each record and which psLens feature uses it, and Whitelist Tables has the SQL inserts you run during installation. You run those inserts yourself, which means you review every record psLens will ever be able to read, and you can narrow the list at any time.

Integration Broker Setup

The two service operations come with routing definitions and handlers and run on your existing Integration Broker gateway. No new gateway, listening connector, or node is required. Because the traffic is ordinary REST service-operation traffic, it is visible in your IB monitoring tools alongside every other integration.

What to Tell Your DBA

  • All queries are reads against PeopleTools metadata tables on the whitelist. SWS has no write path for psLens to call.
  • Query volume is driven by on-demand page views plus a configurable alert interval (default every 5 minutes). See the load FAQ for the breakdown.
  • There is nothing to install or configure at the database layer. The change is entirely PeopleTools objects plus whitelist rows.

Questions

If your security team needs answers in writing before approving the install (object-by-object review, role configuration, whitelist scoping), raise it on the demo call or email chris.malek@cedarhillsgroup.com.

2 - Code & Supply Chain

What code runs in psLens, how it’s built and distributed, dependency posture, and the vulnerability disclosure & patching process.

This page is for security reviewers who need to understand what is running inside psLens before approving its deployment. It covers four questions:

  1. What code is actually running?
  2. Can we audit it?
  3. How is it built and shipped?
  4. How are vulnerabilities found, disclosed, and fixed?

If you’re looking for the higher-level read-only / whitelist story, start with Security & Trust and come back here for the detail.


1. What’s Inside the Image

psLens is a single Go binary plus an embedded NATS server, packaged as a multi-stage Docker image distributed from ghcr.io/cedarhillsgroup/pslens. There is no separate database, message broker, or external worker process; one container is the whole application.

Runtime stack

ComponentPurpose
Go 1.26+Application language; binary statically linked
gorilla/muxHTTP routing
a-h/templServer-rendered HTML templates
Embedded NATS (nats-server/v2)In-process key-value store for sessions, alerts, report output
data-star (datastar.dev)Hypermedia / SSE for interactive UI; no SPA framework
GoldmarkMarkdown rendering for report output
Standard library crypto/aes, crypto/tlsEncryption at rest and in transit

There is no embedded browser, no third-party telemetry SDK, no analytics tracker. The full dependency list is go.mod in the source tree.

Base image

The runtime stage is debian:bookworm-slim with ca-certificates. No shell access is required for normal operation; psLens runs as PID 1.


2. Source Availability and Review

psLens is closed-source. The source tree is not published publicly.

For customers who need to review the code: Cedar Hills Group offers a read-only source review under NDA as part of the procurement process. Mechanics (on-site, screen-share, time-boxed access) are agreed during contracting. Reach out via the contact page to arrange.

This is the same model used by most enterprise PeopleSoft tooling: the binary is yours to run, the source is reviewable under contract, redistribution is not granted.


3. Build and Distribution

Build pipeline

StageWhere it runsWhat it produces
Source commitCedar Hills Group internal repoTagged release commit (semver)
CI buildGitHub Actions, GitHub-hosted runnersMulti-arch Docker image
PublishGitHub Container Registry (GHCR)Private package, tagged vMAJOR.MINOR.PATCH, vMAJOR.MINOR, latest, git SHA

The release pipeline injects the version, commit SHA, and ISO-8601 build timestamp into the binary at compile time via Go ldflags. You can read them back from any running instance via /healthz and the startup banner in container logs. Useful for confirming exactly which build a customer is running.

What we do today

  • Traceable builds. Every image embeds the git SHA and build timestamp in its label and binary; you can map any running container back to the exact source commit that produced it.
  • Pinned tag flavors. Production customers pin to vMAJOR.MINOR (or exact vMAJOR.MINOR.PATCH) so a docker compose pull never surprises them with a major-version change. See Deployment Options for the tag flavors and recommended pinning.
  • Private package distribution. GHCR access is gated by per-customer read-only fine-grained personal access tokens.

What we don’t do yet (roadmap)

  • Image signing with cosign. Planned. Once landed, every published tag will carry a sigstore-verifiable signature and you’ll be able to verify provenance with cosign verify.
  • SLSA build provenance attestation. Planned alongside cosign.

4. Dependency Management

Today

  • go.mod is the single source of truth; all dependencies are pinned by version and content hash (go.sum).
  • Automated scanning. We run govulncheck daily and on every push/PR in our GitHub Actions CI pipeline to verify there are no known exploitable vulnerabilities in our dependencies.
  • Dependency monitoring. Dependabot is enabled to track Go modules, GitHub Actions, and Dockerfile base images, raising automated pull requests for updates.
  • The dependency footprint is intentionally narrow (see the table above); Go standard library does most of the work.

If your security policy requires SBOM artifacts as part of vendor onboarding, ask on the demo call. We can generate a CycloneDX or SPDX SBOM from a tagged build on request.


5. Vulnerability Disclosure and Patching

Reporting a vulnerability

Email security@cedarhillsgroup.com. Please include:

  • Affected version (the git SHA from /healthz is most precise)
  • Reproduction steps or proof-of-concept
  • Your assessment of severity (CVSS or descriptive)

We commit to:

  • Acknowledgement within 1 business day of receipt.
  • Coordinated disclosure. We will agree a disclosure window with the reporter before publishing details.
  • Crediting researchers in the release notes unless they prefer otherwise.

Patch SLA

Specific patch targets (business days for Critical, High, Medium) are disclosed during contracting.

When a fix ships, it goes out as a patch release in the same vMAJOR.MINOR stream you’re already pinned to. docker compose pull && docker compose up -d picks it up. Critical fixes are also announced by email to deployment contacts.

Subscribing to release notes

Release notes are published as GitHub Releases on the source repo. Deployment contacts are notified by email for any release with a security note.


6. What Reviewers Usually Ask

“Is the binary statically linked?” Yes. Go produces a static binary; no system library version drift.

“Does it phone home?” No. There is no outbound connection from a running psLens instance other than (a) to your SWS endpoint and (b) to your SMTP server if you’ve enabled magic-link auth. No telemetry, no update checks, no license-server callbacks.

“What user does it run as inside the container?” Confirm the current default with us on the demo call. Recommendation for self-hosters regardless: run with --user 1000:1000 and a read-only root filesystem; only /data needs to be writable.

“How big is the attack surface?” One HTTP listener (default port 8080 or whatever you configure), serving HTML and Server-Sent Events. No raw socket listeners, no UDP, no message-queue ingress, no plugin loader.


3 - Authentication & Access

How users log in to psLens, the deliberate scope decision behind no in-app RBAC, SSO via reverse proxy today, and native SSO on the roadmap.

This page covers how end users authenticate to psLens, what access controls exist (and which deliberately don’t), and how to front psLens with your existing identity provider today.

For SSO, see SSO Today.


1. How Users Log In Today

psLens ships with optional email magic-link authentication. It is off by default in the shipped config.yaml and must be turned on for production deployments.

When auth.enabled: true:

  1. User visits any psLens URL → redirected to /login.
  2. User enters their email address.
  3. psLens emails a one-time verification code to that address (only if the address is on the configured AuthorizedUsers allowlist).
  4. User enters the code at /verify-code.
  5. Session created in NATS KV, identified by an HTTP-only psLens_auth cookie.
PropertyValue
MechanismEmail one-time code (no passwords)
Session storageNATS KV bucket auth-sessions
Session TTL1 year (configurable)
CookiepsLens_auth, HTTP-only
User allowlistAuthorizedUsers in config.yaml, case-insensitive
Public endpoints (no auth required)/healthz, /static/*, the auth flow itself

There are no end-user passwords for psLens to store, leak, hash, or rotate.

Disabling auth entirely is supported only for sandbox or trusted-network deployments. The shipped config defaults to disabled so a first-time installer can get to a working UI quickly. Flip it on before exposing the instance.


2. The Deliberate Scope Decision: No In-App RBAC

psLens has no role-based access control inside the application. Every authenticated user sees the same set of metadata, can run the same reports, and can browse the same PS objects.

This is intentional, not an oversight:

  • psLens is read-only. It cannot modify PeopleSoft. The worst an authenticated user can do is read metadata.
  • The query surface is whitelisted on the PeopleSoft side by the SWS framework. Even psLens itself cannot query anything off-list. See Security & Trust.
  • The access boundary therefore lives at who is on the AuthorizedUsers list, not at “what role does this user have inside psLens?”. If a user shouldn’t see PS metadata at all, they shouldn’t have a psLens login.

For most customers, the population of people who need psLens (PS developers, sec admins, sys admins, business analysts doing audit work) is small and homogeneous. Adding in-app roles would create configuration overhead without changing the actual blast radius.

If your security policy requires per-user authorization decisions at the application layer, raise it on the demo call. The reverse-proxy patterns below can enforce this without requiring psLens itself to grow an RBAC model.


3. SSO Today: Reverse Proxy

The recommended pattern for any production deployment is to front psLens with a reverse proxy that handles SSO, and turn off the built-in magic-link layer. This delegates authentication to the IdP you already trust.

Common setups:

Reverse proxyIdentity providersNotes
Cloudflare AccessOkta, Azure AD, Google Workspace, OIDC, SAMLNo infrastructure for you to run; works with the fly.io-managed deployment
oauth2-proxyGoogle, GitHub, Azure AD, Keycloak, generic OIDCSelf-hosted; sidecar to psLens
PomeriumAny OIDC, SAMLSelf-hosted; richer policy engine
Tailscale with serveAny SSO that fronts TailscaleNetwork-layer; locks psLens to your tailnet
Nginx / Traefik / Caddy with forward_authAnything that speaks OIDCMost flexible; you own the wiring

The pattern is the same in every case:

  1. The reverse proxy terminates TLS, authenticates the user against your IdP, and only forwards authenticated requests to psLens.
  2. psLens trusts the proxy (binds to a private network or listens on 127.0.0.1).
  3. auth.enabled: false in psLens config. The proxy is the identity boundary.

Cross-link: the TLS termination patterns in Deployment Options cover the same reverse proxies and explain how to wire them up; this page is the identity-layer companion.

What the proxy can do that psLens RBAC could not: enforce group membership (“only the psoft-admins group in Okta”), require MFA, enforce conditional access policies (managed device, geo, time-of-day), and write to your existing IdP audit log.


4. Native SSO on the Roadmap

Native OIDC support inside psLens is planned. No committed date. This will let customers who don’t want a reverse-proxy hop configure their IdP directly in config.yaml.

We are deliberately not promising native SAML. The reverse-proxy patterns above already cover SAML; native OIDC closes the more common gap.

Until native SSO ships, reverse-proxy SSO is production-ready. It is the recommended deployment pattern for every customer with an enterprise IdP.


5. Session Management

ConcernBehavior
Where sessions liveNATS KV, bucket auth-sessions, scoped to this psLens instance
Cookie scopeHTTP-only, marked Secure when served over HTTPS
Idle timeoutNone today. Sessions live until the TTL expires.
Absolute TTL1 year (configurable per deployment)
Logout/logout clears the session entry from NATS KV
Mass invalidationRestart the container, or clear the auth-sessions bucket via nats kv. Useful after a credential incident.

A built-in admin-facing “kill all sessions” UI is on the roadmap. Today the NATS CLI path above is the supported route.


6. What Reviewers Usually Ask

“Can we require MFA?” Yes, by fronting with a reverse proxy that enforces MFA at the IdP layer (any of the proxies above). Magic-link auth on its own is single-factor (control of the email inbox).

“Where does the user email come from on the SWS side?” psLens authenticates its own users via magic-link or reverse-proxy SSO. Those are the people using the psLens UI. psLens authenticates to PeopleSoft via the SWS service account (basic auth, see Code & Supply Chain). The two identity domains are independent. Your psLens users do not need PS accounts.

“Can we revoke a user instantly?” Yes. Remove them from AuthorizedUsers and restart; their next request fails. With reverse-proxy SSO, revoke them at the IdP and they lose access on the next request, no restart needed.

“Does psLens store passwords?” No end-user passwords. The only password-shaped secret psLens holds is the SWS service-account password used to call PeopleSoft, encrypted at rest with AES-256-GCM. See Data Handling & Logging.


4 - 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.


5 - Deployment & Operations

How psLens is deployed, network requirements, sizing, backup, upgrade, DR, monitoring — consolidated for ops and security reviewers.

This page consolidates the operational story that an IT or DBA reviewer needs in one place. It overlaps with Installation and Deployment Options; those are the how-to references, and this page is the what-to-expect security-review companion.


1. Deployment Model

  • One container per customer. Each customer gets a dedicated psLens deployment: separate process, separate NATS instance, separate /data volume.
  • No shared multi-tenant backend. There is no Cedar Hills Group SaaS plane that customer instances talk to. Your psLens instance talks to your PeopleSoft and (optionally) your SMTP, and that is it.
  • Two hosting options:
    ModeOperated byWhere it runs
    ManagedCedar Hills Groupfly.io, in the region you choose at provisioning
    Self-hostedYouDocker, docker-compose, Kubernetes, or systemd on a Linux VM. Your cloud, on-prem, or air-gapped.

The choice is reversible. You can start managed and migrate to self-hosted (or vice versa). The data volume is portable and the configuration travels.


2. Network Requirements

Inbound

FromToWhy
Your users (browsers)psLens UI on HTTPS (port per your TLS pattern)The whole point
Your monitoring systemGET /healthzLiveness check, returns 200 OK

Outbound

FromToWhen
psLensYour SWS endpoint (HTTPS)Every request that hits PeopleSoft
psLensYour SMTP serverOnly if auth.enabled: true and you’re using built-in magic-link
psLensAnywhere elseNever. No telemetry, no update checks, no callback to Cedar Hills Group.

This means psLens runs cleanly behind strict egress filtering. Allow it the SWS hostname (and SMTP host if applicable) and deny everything else.

TLS termination

Cross-link: Deployment Options → TLS compares 6 patterns (native cert, Let’s Encrypt, Caddy, nginx, Traefik, Tailscale Serve). Pick the one that matches your existing edge.


3. Sizing

Recommended minimums:

ResourceMinimumNotes
CPU1 vCPUMatches the smallest fly.io machine class currently in production
RAM512 MBMost requests are well under this; reports can spike briefly
Disk1 GB persistentNATS KV + uploaded project archives; grow if you upload many projects
Network~negligibleMetadata queries are small; most traffic is HTML rendering

For deployments handling many concurrent users or running heavy reports, scale up to 2 vCPU / 1 GB RAM. psLens is a single Go process; vertical scaling is the path, and there is no clustering model today.


4. Backup and Restore

What to back up

PathContentsLoss impact
/data/natsAlert history, report output, encrypted credentials, sessions, recently-viewedLose alert/report history; users re-enter PS DB passwords
/data/projectsUploaded PS project archivesRe-upload from source
/app/config.yamlConfigurationRe-create from your config-management tooling
PSLENS_MASTER_KEY (env var)Encryption key for credentials in /data/natsWithout it, the encrypted credentials in NATS KV are unreadable. Back up out of band (password manager, vault, secret store).

Suggested cadence

  • Nightly tarball of /data/nats and /data/projects to your backup target.
  • 14–30 day retention for daily snapshots; longer if your audit policy requires.
  • Master key stored separately (so a single-system compromise can’t yield both).

Example backup script (Docker host):

#!/usr/bin/env bash
set -euo pipefail
TS=$(date -u +%Y%m%dT%H%M%SZ)
docker run --rm \
  --volumes-from pslens \
  -v "$BACKUP_DIR":/backup \
  alpine \
  tar czf "/backup/pslens-${TS}.tar.gz" /data

Restore

  1. Stop the container.
  2. Restore the tarball into a fresh /data volume.
  3. Ensure PSLENS_MASTER_KEY matches the key that encrypted the credentials.
  4. Start the container.

5. Disaster Recovery

Today’s posture:

  • For self-hosted: DR is whatever your existing container DR posture is. psLens fits the same pattern as any small stateful Go service: restore the data volume, restart.
  • For managed (fly.io): redeployment is fast because all state fits in one volume. Cedar Hills Group operates the deployment; RTO/RPO targets for managed deployments are disclosed during contracting.
  • No multi-region replication of psLens state today. The single-customer scope makes this rarely worth the complexity, but if your contract requires it, raise it on the demo call.

If you need a higher DR posture than this, the answer is usually “self-host and use your existing DR tooling for the volume.” Cedar Hills Group can help structure that.


6. Monitoring

What ships today

  • GET /healthz returns 200 OK if the process is alive. Liveness check only; no readiness signal beyond startup completion.
  • Structured slog to stderr for every request and every error. Ship to your SIEM via your container runtime’s log driver.
  • Startup banner in logs: version, commit SHA, build timestamp. Useful for confirming an upgrade landed.
  • Connection-status UI inside psLens shows live SWS reachability for each configured database.

What doesn’t ship today

  • No Prometheus /metrics endpoint. Planned. No committed date.
  • No built-in alerting, in the sense of “psLens noticing it has a problem and notifying you.” That is your monitoring system’s job, fed by /healthz and the log stream.

Recommended wiring for a customer environment:

SignalHow to monitor
Process aliveGET /healthz from your uptime monitor every 30–60 s
ErrorsForward stderr to your log aggregation; alert on error-rate spikes
Auth failuresSame: the request log includes status codes
SWS reachabilitypsLens already shows this; if you want it externalized, build a small probe against /healthz

7. Upgrades and Rollback

Pin production to a vMAJOR.MINOR tag. To upgrade:

docker compose pull
docker compose up -d

The data volume survives the restart. Schema migrations on the NATS KV layer (if any) run automatically on first start of the new version.

To roll back, pin to the prior vMAJOR.MINOR.PATCH tag, docker compose up -d. Downgrade compatibility within a vMAJOR.MINOR is guaranteed; across major versions, check the release notes.

Breaking change contract: breaking changes only land in major version bumps and are called out explicitly in release notes. Patch and minor releases preserve config compatibility.

Cross-link: Deployment Options → Image Tags for the full tag-flavor table.


8. Multi-Environment Support (DEV / TEST / PROD)

A single psLens instance can be configured to connect to multiple PeopleSoft databases (DEV, TEST, PROD, demo) via entries in config.yaml. The database selector appears on every search and report page.

This is usually the right deployment shape: one psLens instance per psLens user community, configured to see every PS environment that community needs. It is rarely useful to run multiple psLens instances unless those communities have non-overlapping access requirements that need to be enforced at the network layer.


9. DBA Concerns: What psLens Does to Your PS Server

For PeopleSoft admins who need to sign off on the load profile:

PropertyBehavior
Connection typeHTTPS to SWS, basic auth, no JDBC, no direct DB connection
Read or writeRead-only. No code path issues INSERT, UPDATE, or DELETE.
Table coverageOnly whitelisted PeopleTools metadata tables (PSRECDEFN, PSPNLDEFN, PSAUTHITEM, process scheduler, IB tables, etc.)
Query shapeMostly short metadata reads. Reports use a 90-second QuerySlow path; nothing runs longer.
ConcurrencyOne concurrent request per active user; small (handful) at any moment for typical customers
Service account permissionsRead on whitelisted tables; no write, no execute

The PS-side audit trail (SWS query log) captures every query psLens issues with timestamps and the SWS service-account OPRID. If psLens is misbehaving, that log shows what it actually did.

Cross-link: Installation → Whitelisting Tables for the full list and SQL.


6 - Compliance & Vendor

SOC 2 posture, GDPR / personal-data handling, DPA, sub-processors, business continuity, and how psLens fits in a vendor-risk review.

This page is for procurement, legal, and vendor-risk reviewers. It states current posture plainly, including where certifications do not yet exist.

If you’re filling out a vendor questionnaire (SIG, CAIQ, custom), the Security Questionnaires section is the right place to start.


1. SOC 2 — Current Posture

Cedar Hills Group is not SOC 2 certified today. Certification is on the roadmap. No committed date.

In the interim, this site documents the controls a SOC 2 Type II report would cover, so a reviewer can map them to their own framework. The relevant Trust Service Criteria and where they’re addressed:

TSCWhere addressed
Security (access controls, encryption, vuln mgmt)Authentication & Access, Data Handling & Logging, Code & Supply Chain
Availability (operational redundancy)Deployment & Operations; single-tenant, per-customer isolation
Confidentiality (limiting access to sensitive info)Read-only design, table whitelist on PS side, encryption at rest for credentials. See Security & Trust.
Processing Integrity (system processing is complete, valid, accurate)Query results are not transformed; reports are deterministic given fixed input; no write path to PS
Privacy (handling of personal info)Data Handling & Logging → Personal Data (PII)

This map is not a SOC 2 report; it is a vendor-side description of controls. We will fill out your SIG, CAIQ, or in-house questionnaire and return it (see below).


2. GDPR and Personal Data

  • psLens does not persist PeopleSoft user PII. There is no stored copy of employee, operator, or HR records.
  • psLens does process PeopleSoft user PII at request time when users search Users / OPRIDs / EMPLIDs. Data is rendered to the browser and discarded.
  • For GDPR purposes, the customer (the PeopleSoft owner) is the controller; psLens / Cedar Hills Group is the processor.

What this means in practice:

TopicpsLens posture
Data Processing Agreement (DPA)Available on request as part of the contract
Sub-processorsSee Sub-Processors below
International data transfersSelf-hosted: you choose. Managed: you choose the fly.io region at provisioning.
Data subject access requestsSource data is in PeopleSoft; the customer handles requests at the source of record. psLens has nothing persisted to deliver or delete.
Right to erasureSame. psLens stores no PS user PII to erase.
Audit / records of processingRequest-level logging is in your container runtime; SWS-side query log on the PS side. See Data Handling & Logging → Audit Logging.

For CCPA, the answer mirrors GDPR: psLens does not “sell” data, does not retain data, and processes only at request time.


3. Data Residency

DeploymentWhere data lives
Managed on fly.ioThe fly.io region you choose at provisioning. Cedar Hills Group does not move data between regions.
Self-hostedWherever you run the container: your cloud, your on-prem, or your air-gapped network
Air-gappedFully supported. psLens does not require outbound internet at runtime beyond reaching your SWS endpoint.

There is no shared multi-tenant backend, so there is no place for data to “leak” into a different region by accident.


4. Sub-Processors

The sub-processor list depends on the deployment mode you choose:

DeploymentSub-processorWhy
Managed (any)fly.ioApplication hosting
Managed or self-hosted with magic-link authYour chosen SMTP provider (or Cedar Hills Group’s, if not specified)Delivering one-time auth codes
AllGitHub (GHCR)Image distribution; only at docker pull time, not at runtime

Self-hosters who don’t use magic-link auth have no Cedar Hills Group sub-processors at runtime. You run the infrastructure end to end.

The specific SMTP provider used by default for managed deployments is named during contracting so it can be reviewed against your vendor list.

Notification of sub-processor changes is provided in the DPA and in writing to deployment contacts.


5. Contract, SLA, and Termination

TopicPosture
Contract lengthNegotiated per customer; typical terms discussed on the demo call
SLA (managed)Uptime targets and support response targets are disclosed during contracting
SupportSetup assistance included; ongoing support terms in the agreement
Termination & data returnAll customer state lives in the per-customer /data volume. On termination, you can take a final tarball before the instance is destroyed. Self-hosters keep everything by definition.
Pricing$500/month subscription + one-time setup fee ($2,500 managed / $4,500 self-hosted). Excludes multi-client hosting providers.
Liability and insuranceCommercial general liability and cyber policy details available on request during contracting

6. About Cedar Hills Group

Cedar Hills Group is a PeopleSoft consultancy. The same team that built the SWS framework (the bounded REST API that psLens uses to talk to PeopleSoft) builds psLens, so the access path psLens uses is one we control end to end.

What this means for vendor reviewers:

  • The team has run real PS environments for real customers and built psLens out of that operational need.
  • Cedar Hills Group is reachable and contactable; this is not a self-service SaaS where you can’t get a human on a call. See contact.

More on the company: cedarhillsgroup.com.


7. Business Continuity: What Happens If Cedar Hills Group Goes Away

A fair question in any vendor review:

  • You keep the Docker image you’re running. GHCR can rotate tokens or change ownership; the image you’ve already pulled keeps working. Pin to a specific vMAJOR.MINOR.PATCH and you have an indefinite-life binary.
  • Self-hosting works without Cedar Hills Group infrastructure. No runtime callback, no license check, no cloud control plane. If our domain disappeared tomorrow, every self-hosted instance keeps running.
  • Managed deployments could be migrated to self-hosted. All state is in the per-customer /data volume. Cedar Hills Group commits to providing the volume and configuration on termination so you can restart it on your own infrastructure.
  • Source escrow. Available on request for enterprise contracts.

Together: a binary you already hold, a portable data volume, and (on enterprise contracts) source escrow. That is the answer to “what is our exposure if the vendor goes away.”


8. Security Questionnaires

We complete the following questionnaires on request as part of an evaluation:

  • SIG Lite. Standard short form.
  • SIG Core. Long form.
  • CAIQ (Cloud Security Alliance). For cloud-shape reviews.
  • Your own custom questionnaire. Preferred, since it asks what your team actually cares about.

To kick this off, email chris.malek@cedarhillsgroup.com with the questionnaire attached, or raise it on the demo call.

For questions that are common across questionnaires, the answer often already lives in one of the pages below. Cross-referencing those pages in your questionnaire response is encouraged.