@ordinatio/security
v1.0.3
Published
**Agentic-first Security Control Plane** for any Node.js application — 5-layer architecture with trust evaluation, policy engine, enforcement gates, integrity chains, and machine-readable recovery guidance on every decision.
Downloads
231
Readme
@ordinatio/security
Agentic-first Security Control Plane for any Node.js application — 5-layer architecture with trust evaluation, policy engine, enforcement gates, integrity chains, and machine-readable recovery guidance on every decision.
Zero framework dependencies. Uses a minimal SecurityDb interface — works with Prisma, Drizzle, or any ORM that can read/write an ActivityLog-shaped table.
500 tests. 35 error codes. 31 source files. 40+ security event types. 18-category enterprise test suite.
5-Layer Architecture
Layer 5: Integrity — SHA-256 hash chains, tamper detection, content verification
Layer 4: Enforcement — blacklists (IP/principal/org), action gate, nonce replay protection
Layer 3: Policy — trust evaluator, policy engine, security intents, playbooks
Layer 2: Detection — brute force, account takeover, thresholds, pattern matching
Layer 1: Logging — 40+ event types, queries, statistics, convenience functions
+Principal Context — trust binding (who, what type, which org, auth method)
Cross-cutting:
Security Posture — getSecurityPosture() — one call, full situational awareness
Alert Recovery — every alert includes impact + action + allowed followups
Summary Layer — summarizePosture() for agents and dashboardsDesign principle: Agents never guess whether something is safe. They ask Security. Every response includes what happened, how severe it is, whether work can continue, and what to do next.
Installation
npm install @ordinatio/securityOr via the Ordinatio Domus orchestrator:
npx ordinatio add securityQuick Start
import {
logSecurityEvent,
checkSecurityPatterns,
evaluateTrust,
evaluatePolicy,
shouldBlockAction,
getSecurityPosture,
summarizePosture,
buildPrincipalContext,
SECURITY_EVENT_TYPES,
} from '@ordinatio/security';
// 1. Log a security event
const event = await logSecurityEvent(db, {
eventType: SECURITY_EVENT_TYPES.AUTH_LOGIN_FAILED,
ip: '192.168.1.1',
principal: buildPrincipalContext({ principalId: 'unknown', principalType: 'user' }),
details: { email: '[email protected]', reason: 'user_not_found' },
});
// 2. Auto-detect attack patterns
const alerts = await checkSecurityPatterns(db, event);
// 3. Evaluate trust for an operation
const trust = evaluateTrust({
issuer: 'vendor.com',
signatureValid: true,
dmarcStatus: 'pass',
nonceValid: true,
ttlValid: true,
orgPolicy: { trustedDomains: ['vendor.com'] },
});
// → { trustTier: 1, trustScore: 100, reasons: ['All trust checks passed'] }
// 4. Check if an action should be blocked
const gate = await shouldBlockAction(db, {
principal: { principalId: 'agent-coo', principalType: 'agent', trustTier: trust.trustTier },
action: 'process_payment',
nonce: 'unique-request-id',
}, { blacklist, nonceStore, policies });
// → { blocked: true, reason: '...', recovery: { nextAction: '...', safeAlternatives: [...] } }
// 5. Get full security posture in one call
const posture = await getSecurityPosture(db, {
principal: { principalId: 'admin', principalType: 'user', trustTier: 2 },
});
console.log(summarizePosture(posture));
// "Security Posture: verified (tier 1, risk 30/100)\nActive alerts: 2 total\n CRITICAL: 1\n..."Key Agentic-First Design Principles
- One call for full context —
getSecurityPosture()replaces querying 12 things - Every denial includes recovery —
{ nextAction, safeAlternatives[] }, never just "no" - Alerts are decision packets —
{ impact, recovery, allowedFollowups }, not just notifications - Trust is centralized —
evaluateTrust()is one shared primitive, not per-module reinvention - Playbooks are machine-readable — agents follow incident response without human scripting
- Security intents — uniform language:
VERIFY_IDENTITY,QUARANTINE_EVENT,ESCALATE_TO_HUMAN - Discoverable API —
_actionson posture responses so agents discover capabilities without docs
Database Interface
The package never imports Prisma or any ORM. It accepts a SecurityDb object:
interface SecurityDb {
activityLog: {
create: (args) => Promise<ActivityLogRecord>;
findMany: (args) => Promise<ActivityLogRecord[]>;
findFirst: (args) => Promise<ActivityLogRecord | null>;
findUnique: (args) => Promise<ActivityLogRecord | null>;
count: (args) => Promise<number>;
update: (args) => Promise<ActivityLogRecord>;
};
}A Prisma client satisfies this naturally. Everything is stored in ActivityLog with action prefixes: security.* for events, alert.* for alerts.
Event Types (40+)
| Category | Events | Default Risk | |----------|--------|-------------| | Authentication | login success/fail, logout, password change, session expired, account locked, suspicious activity, MFA, password reset | LOW–HIGH | | Access Control | permission denied/granted/revoked, role changed, unauthorized resource | LOW–HIGH | | API Security | rate limit exceeded, API key CRUD, header missing, CSRF failed, input blocked | MEDIUM–HIGH | | Data Security | sensitive data accessed/exported, bulk operations, PII accessed | LOW–HIGH | | System | config changed, feature flag toggled, scan completed, vulnerability detected, anomaly | LOW–CRITICAL | | Agent | sensitive data to LLM, tool blocked by policy | MEDIUM–HIGH | | Integration | OAuth refresh/revoke, webhook signature invalid, external API error | LOW–HIGH |
Alert Thresholds (Configurable)
| Pattern | Threshold | Window | Alert Level | |---------|-----------|--------|-------------| | Failed logins | 5 | 15 min | HIGH | | Failed logins (sustained) | 10 | 60 min | CRITICAL | | Rate limit hits | 10 | 5 min | HIGH | | Permission denials | 10 | 10 min | HIGH | | Data exports | 5 | 60 min | CRITICAL | | CSRF failures | 3 | 5 min | CRITICAL | | Blocked inputs | 20 | 10 min | HIGH | | Account lockouts | 3 | 60 min | CRITICAL | | Invalid webhooks | 5 | 10 min | HIGH |
Error Codes (SECMON_100–432)
| Range | Category | Count | |-------|----------|-------| | 100–106 | Event Logging | 7 | | 200–206 | Alert Management | 7 | | 300–304 | Detection Engine | 5 | | 400–406 | Integrity Layer | 7 | | 410–418 | Trust & Policy | 9 | | 420–432 | Enforcement / Replay | 10 |
Every error includes: code, file, function, severity, recoverable flag, description, and diagnosis steps.
API Reference
Layer 1: Logging
logSecurityEvent(db, input, callbacks?)— Core logginglogLoginSuccess/Failure/RateLimitExceeded/PermissionDenied/SuspiciousActivity— Convenience wrappersgetSecurityEvents(db, options?)— Query with filters, paginationcountSecurityEventsInWindow(db, options)— Threshold checksgetUserSecurityHistory / getSecurityEventsByIp / getRecentHighRiskEvents / getSecurityEventStats
Layer 2: Detection
checkSecurityPatterns(db, event, callbacks?)— Run all detectorscheckForBruteForce / checkForAccountTakeover / checkForSuspiciousPatterns
Layer 3: Policy
evaluateTrust(input)→{ trustTier: 0|1|2, trustScore: 0-100, reasons[] }evaluatePolicy(context, policies)→{ decision, recommendation, constraints }resolveIntent(intent, context, db, callbacks?)— Named security operationsgetPlaybookForAlert(alertType)— Machine-readable incident response
Layer 4: Enforcement
shouldBlockAction(db, context, config, callbacks?)→{ blocked, reason, recovery }InMemoryNonceStore— LRU+TTL replay protectionCompositeBlacklist— IP/principal/org with TTLgetThrottleDelay(excess, baseMs)— Exponential backoff
Layer 5: Integrity
computeEventHash / computeIntegrityHash— SHA-256 deterministic hashingverifyEventChain(events)— Tamper-evident chain verificationverifyContentIntegrity / verifyChainLink / verifyHashChain— Generic primitivesbuildHashedEvent / buildIntegrityMetadata / getLastHash
Cross-cutting
buildPrincipalContext / validatePrincipal / describePrincipal— Trust bindinggetSecurityPosture(db, options?, callbacks?)— Full situational awarenesssummarizePosture(posture)— Token-efficient text for LLM context windowsbuildAlertRecovery(alert)— Impact + action + followupsbuildSecurityHeaders(isDev?) / SECURITY_HEADERS— HTTP security headersInMemoryKeyStore / resolveKeyForTrust— Key rotation with grace windows
Alert Management
createAlert / findExistingAlert / getActiveAlerts / getAlertsacknowledgeAlert / resolveAlert / getAlertStats / activityToAlert
Audit
runSecurityAudit(db, runner, triggeredBy?, callbacks?)— Pluggable audit runnergetLastSecurityAudit(db)— Most recent result
Enterprise Test Suite (18 Categories)
| Category | Tests | What It Proves | |----------|-------|----------------| | Policy truth table | 25 | Correct allow/deny/escalate for every trust×action combination | | Fail-safe | 15 | Safe degradation on DB failure, callback panic, malformed input | | Tamper-evident chain | 17 | Modified/deleted/reordered/injected events detected | | Replay attacks | 12 | Concurrent nonce replay blocked, exactly-once execution | | Key rotation | 22 | Grace windows, revocation, trust continuity across rotation | | Threshold edges | 9 | No off-by-one on alert boundaries | | Posture snapshots | 6 | Deterministic posture output (golden tests) | | Adversarial metadata | 18 | 10KB+ payloads, SQL/XSS injection, prototype pollution | | Hypermedia contract | 21 | Every response includes _actions, recovery, constraints | | Recovery paths | 10 | Every denial tells the agent what to do next | | Summary contract | 18 | Summaries match machine state, don't omit restrictions | | Stress/load | 8 | 10k trust evals, 100k nonces, 1k gate checks | | Race conditions | 7 | No double-creation, no stale overwrites | | Chaos | 9 | DB down, callback panic, clock skew — all fail safe | | Red team scenarios | 6 | Fake vendor payment, brute force wave, malicious key rotation | | Regression corpus | 17 | Known attack patterns still recognized | | Adversarial tampering | 14 | Chain corruption at every position detected | | Time edge cases | 11 | TTL boundary, nonce expiry, clock skew |
Domus Integration
When used via @ordinatio/domus, the security module:
- Uses the existing
ActivityLogtable (no additional schema) - Has no seed data (events are generated by application behavior)
- Provides
DomusSecurityApiwith 12 pre-wired methods
License
MIT
