@afterauth/core
v0.0.4
Published
Deterministic trust decision engine for progressive trust after auth
Readme
@afterauth/core
Deterministic trust decision engine for progressive trust after auth.
AfterAuth evaluates user trust signals against a policy ruleset and returns a decision — allow, allow_limited, delay, require_verification, or deny — along with a tamper-proof evidence hash for auditability.
Installation
npm install @afterauth/coreUsage
import { evaluate } from "@afterauth/core";
const decision = evaluate({
request: {
requestId: "req_001",
requestType: "credit_unlock",
userId: "user_123",
benefitType: "trial_credits",
requestedAmount: 500,
signals: {
email: "[email protected]",
emailVerified: true,
hasPaymentMethod: false,
accountAgeDays: 3,
},
metadata: { source: "onboarding" },
},
priorEvents: [],
policyRuleSet: null, // uses DEFAULT_POLICY_RULE_SET
policyId: null,
policyName: null,
});
console.log(decision.outcome); // "allow_limited"
console.log(decision.approvedAmount); // number
console.log(decision.reasonCodes); // ["work_email_limited_unlock"]
console.log(decision.evidenceHash); // sha256 of frozen contextOutcomes
| Outcome | Meaning |
|---|---|
| allow | Full access granted |
| allow_limited | Partial access granted up to approvedAmount |
| delay | Hold request for later processing |
| require_verification | Additional verification needed before proceeding |
| deny | Access denied |
Policy Rules
Policies are evaluated first-match-wins against a set of typed conditions:
import { evaluateRules } from "@afterauth/core";
import type { PolicyRuleSet } from "@afterauth/core";
const policy: PolicyRuleSet = {
version: 1,
defaultOutcome: "allow_limited",
defaultApprovedRatio: 0.2,
rules: [
{
id: "verified_payment",
conditions: { hasPaymentMethod: true },
outcome: "allow",
approvedRatio: 1,
reasonCode: "payment_method_present",
},
{
id: "work_email",
conditions: { emailDomainType: ["work"] },
outcome: "allow_limited",
approvedRatio: 1,
maxApprovedAmount: 500,
reasonCode: "work_email_limited_unlock",
},
],
};Supported Signals
| Signal | Type | Description |
|---|---|---|
| email | string | User email address |
| emailVerified | boolean | Email verification status |
| hasPaymentMethod | boolean | Payment method on file |
| accountAgeDays | number | Days since account creation |
| githubAccountAgeDays | number | Days since GitHub account creation |
| activationCount | number | Number of activation events |
| multiAccountDetected | boolean | Abuse signal: multiple accounts |
| velocityExceeded | boolean | Abuse signal: request velocity |
| disposableEmail | boolean | Disposable email domain detected |
Auditability
Every decision includes a frozenContext snapshot and a deterministic evidenceHash (SHA-256) so decisions can be replayed and verified later:
console.log(decision.frozenContext); // full signal + policy snapshot at decision time
console.log(decision.evidenceHash); // sha256 hash of frozenContextLicense
MIT
