◆PRISMZTNA

07 / 12Prism Systems · Cloud-Native & Developer Infrastructure

Zero-trust access that checks every request, not just the login

A zero-trust network access proxy: a readable policy language with deny-overrides, device posture scoring, device-bound HS256 session tokens with key rotation, step-up MFA, continuous verification that revokes sessions when posture drops, an anycast PoP mesh with outbound-only app connectors, and a hash-chained audit log.

Zero dependenciesPolicy language + linterDevice-bound tokensContinuous verificationTamper-evident audit
Live simulator

Six users, five PoPs, six private apps

Every dot is a request decided at the nearest PoP. Compromise a laptop and watch its session get revoked, log in from a sanctioned country, kill a PoP to see traffic re-route, rotate keys, or edit the policy live and apply it.

paused
users → PoPs → private apps
Decisions / s
Overlay RTT (ms)
Policy —
Decision inspector latest
Audit log
Features

What's inside the engine

Real algorithms, not mock-ups. The simulator above runs the exact same code you import.

⌘

Policy language

Declare apps with tags, then allow / deny rules with targets (*, names, tag:prod) and conditions using and or not == != < >= in matches, durations like 15m, and require mfa within 15m.

⚖

Deny overrides, default deny

All matching deny rules are checked first, then the first matching allow wins. Anything else is denied, with the failed conditions of every candidate rule in the reason.

◉

Explainable decisions

The evaluator records each comparison with the value it saw, so every decision shows which rule fired and why (device.score >= 80 ← 77).

💻

Device posture

Weighted checks for disk encryption, EDR, patch age (with partial credit), jailbreak, firewall, screen lock and MDM produce a 0–100 score and a trusted / limited / untrusted tier.

🔑

Device-bound tokens

HS256 tokens carry a cnf.dev thumbprint, audience and expiry, use constant-time signature checks and reject alg: none. Key rotation keeps the previous key for a grace period.

↻

Continuous verification

Posture is re-evaluated on every request. If a device drops below the floor its sessions are revoked immediately, not at the next login.

⬡

PoP mesh

Users anycast to the nearest healthy PoP, traffic crosses a private backbone (Dijkstra on RTT), and app connectors dial out to two PoPs, so private networks need no inbound ports.

⛓

Hash-chained audit

Every login, decision, step-up and revocation commits to the previous entry with SHA-256. Editing any entry breaks the chain at that sequence number.

How it works

From request to result

Authenticate

The IdP verifies the user. The broker scores the device and refuses login below the posture floor, then signs a token bound to that device.

Verify

Each request presents the token and device id. Signature, audience, expiry, key id and device binding are checked, and the session must still exist.

Re-check posture

Device signals are scored again. A compromised device loses its sessions on its next request.

Decide

The policy sees user, device, geo, time and MFA age. Deny rules first, then allows, then default deny. Step-up rules return a challenge instead of an allow.

Route + audit

Allowed traffic goes ingress PoP → backbone → egress PoP → connector → app with identity headers. Every outcome lands in the audit chain.

Architecture

System design

Every box is a module in src/. Data flows left to right.

tokenallowCLIENTUser + devicetoken · posture signalsIdP / MFAlogin · step-upEDGE POPEnforcementverify · posturePolicy enginedeny-overridesMESHBackboneDijkstra on RTTAudit chainsha-256 linkedPRIVATE APPSConnectoroutbound tunnelsAppidentity headers
Use it

Ship it in your own stack

Zero dependencies. Works in Node.js 18+ and modern browsers.

example.js
import { Broker, Mesh, Policy, posture } from "prism-ztna";

const policy = `
app prod-db  host "10.0.4.12:5432"  tags [prod]
deny  "geo"      *         when geo.country in ["KP", "IR"]
deny  "posture"  tag:prod  when device.tier != "trusted"
allow "sre"      tag:prod  when "sre" in user.groups and device.score >= 80 require mfa within 15m`;

const zt = new Broker({ policy, directory, mesh: new Mesh({ connectors }) });
const { token, sid } = zt.login("riya", "mbp-riya");          // posture-checked, device-bound token

const d = zt.access(token, "prod-db", { deviceId: "mbp-riya" });
d.effect;   // "allow" | "deny" | "challenge"
d.rule;     // "sre"
d.trace;    // every rule and comparison, with the values it saw
d.route;    // { path: ["bom"], rtt: 1.1 }

zt.stepUp(sid);                       // after WebAuthn / TOTP
zt.revokeDevice("mbp-riya", "lost");  // kill every session on a device
zt.verifyAudit();                     // { ok: true, entries, head }

new Policy(policy).lint();            // unknown targets, unreachable apps, unconditional rules
terminal
$ npx github:krishyaa06/prism-ztna demo
$ npx github:krishyaa06/prism-ztna lint examples/policy.ztna
$ npx github:krishyaa06/prism-ztna eval --user arjun --app prod-db
$ npx github:krishyaa06/prism-ztna posture
$ npx github:krishyaa06/prism-ztna route --user riya --app gitlab --down fra
$ npx github:krishyaa06/prism-ztna serve --port 8080
terminal
# use the CLI without installing
$ npx github:krishyaa06/prism-ztna --help

# or add the engine to your project
$ npm install github:krishyaa06/prism-ztna

# run the simulator locally
$ git clone https://github.com/krishyaa06/prism-ztna.git && cd prism-ztna
$ npx serve .   # then open http://localhost:3000