@useoneauth/trust
v1.0.0
Published
> Phase 7 — Trust Engine. Continuous, adaptive trust evaluation: signals → risk score → allow / step-up / deny.
Downloads
314
Readme
@useoneauth/trust
Phase 7 — Trust Engine. Continuous, adaptive trust evaluation: signals → risk score → allow / step-up / deny.
Pure TypeScript. A TrustEngine composes pluggable signals (device, location,
credential-type, behavior, context-drift), each contributing risk points; the engine
sums to a score, maps it to an outcome by thresholds, and lets critical signals
(session hijacking / context drift) hard-gate the result. A TrustWatcher runs the
engine as a watcher over the event stream — continuous, per-action revaluation rather
than an inline proxy.
Implements the runtime-identity principles in
../../context/runtime-identity-principles.md (#1–#6).
Install
// package.json
{ "dependencies": { "@useoneauth/trust": "workspace:*" } }Usage
import {
TrustEngine, TrustWatcher,
DeviceSignal, LocationSignal, CredentialTypeSignal, BehaviorSignal, ContextDriftSignal,
} from "@useoneauth/trust"
import { EventBus, InMemoryEventStore } from "@useoneauth/events"
const events = new EventBus(new InMemoryEventStore())
const engine = new TrustEngine({
signals: [new DeviceSignal(), new LocationSignal(), new CredentialTypeSignal(), new BehaviorSignal(), new ContextDriftSignal()],
events,
})
// Session bound to device "d1" but the request comes from "dX" → hijacking.
const decision = await engine.evaluate({
subjectId: "u1",
sessionId: "s1",
device: { deviceId: "dX" },
expected: { device: { deviceId: "d1" } },
})
// { outcome: "deny", score: 100, level: "low", reason: "score 100 → deny (critical: context_drift)", signals: [...] }
// Run continuously as a watcher over the event stream:
new TrustWatcher(engine, events, {
events: ["SESSION_CREATED", "TOKEN_ISSUED"],
toContext: (e) => {
const p = e.payload as { identityId?: string; sessionId?: string }
return p.identityId ? { subjectId: p.identityId, ...(p.sessionId ? { sessionId: p.sessionId } : {}) } : null
},
onDecision: (d) => {
if (d.outcome !== "allow") {/* feed policy stepUp obligation / revoke session */}
},
}).start()Model
- Signals — each
TrustSignal.evaluate(context)returns{ signal, risk, critical?, reason? }. Built-ins:DeviceSignal,LocationSignal,CredentialTypeSignal,BehaviorSignal, and the criticalContextDriftSignal(device/location mismatch vs the bound baseline). - Engine —
score = Σ risk; base outcome by thresholds (stepUpdefault 30,denydefault 70); any critical signal withrisk > 0hard-gates to at leaststep_up(ordenyif its risk reaches the deny threshold). The final outcome is the most severe of the base and critical outcomes. - Outcomes —
allow/step_up/deny;step_upis consumed by the Phase-6 policystepUpobligation at the orchestration layer above. - Watcher — subscribes to event types, maps each event to a
TrustContext, evaluates, and reports viaonDecision. Observability-driven, never inline.
Events
TRUST_EVALUATED on every evaluation (subjectId, sessionId, outcome, score, level,
signals) via the @useoneauth/events-core EventPublisher — wire the Phase-5 EventBus
for a durable, replayable trust audit trail.
Scope
No ML/probabilistic scoring; drift is equality-based (no impossible-travel-by-time geo
math); the expected baseline is passed in the context (no baseline store yet); no
DB/HTTP/CLI. Trust→policy and trust→revocation wiring is orchestration above the package.
See ARCHITECTURE.md.
