Platform & Architecture Docs
Explore Entitle's architecture, domain-driven design, technical implementation, and vision. All documentation is now organized by domain, technical, sales, and future roadmap.
Domain-Driven Design (DDD)
Explore the core architecture and bounded contexts of Entitle. View DDD Docs →
Technical Documentation
Technical implementation, API architecture, CI/CD, and technology stack. View Technical Docs →
Sales & Vision
Vision, executive summaries, and feature enablement strategy. View Sales & Vision Docs →
Future & Roadmap
Ideas, future contexts, and usage tracking. View Future & Roadmap Docs →
Decision Evaluation API
The core API endpoint evaluates whether a principal is allowed to access a capability. It is stateless, deterministic, and low-latency (P95 < 10ms target).
Endpoint
POST /v1/evaluate Request Format
{
"capability": "export-data",
"principal": {
"user_id": "user-123",
"org_id": "org-456"
},
"context": {
"environment": "production"
}
} Response Format
{
"allowed": true,
"reason": "policy_match",
"policy_version": "v1"
} Key Characteristics
- Tenant context resolved via authentication - Never from request payload
- Deterministic - Same input always produces same output
- Stateless - No session state maintained
- Fast - Target P95 latency under 10ms
Authentication & Tenant Isolation
Entitle uses API key-based authentication in the MVP. Each tenant receives unique API keys per environment (dev/staging/prod).
Authentication Header
Authorization: Bearer YOUR_API_KEY Tenant Isolation Guarantees
- One API key per tenant per environment
- Tenant identity derived from credentials, never from request payload
- Hard tenant isolation at data layer (row-level security)
- No cross-tenant visibility possible
SDK Usage (Node.js/TypeScript)
The Entitle Node.js SDK provides a safe Anti-Corruption Layer between your application and Entitle. It is thin by design—policy logic stays in Entitle, not the SDK.
SDK v1 Scope
- Typed TypeScript interface
- Call
/evaluateendpoint - In-memory TTL caching
- Timeout & retry handling
- Shadow mode support
Installation
npm install @entitle/node-sdk Basic Usage
import { EntitleClient } from '@entitle/node-sdk';
const entitle = new EntitleClient({
apiKey: process.env.ENTITLE_API_KEY,
});
// Check capability access
const allowed = await entitle.can("export-data", {
userId: "user-123",
orgId: "org-456"
});
if (allowed) {
exportData();
} else {
throw new ForbiddenError("Export not available on your plan");
} Express.js Middleware Pattern
import { EntitleClient } from '@entitle/node-sdk';
const entitle = new EntitleClient({
apiKey: process.env.ENTITLE_API_KEY,
});
// Reusable middleware
const requireCapability = (capability: string) => {
return async (req, res, next) => {
const { userId, orgId } = req.user;
try {
const allowed = await entitle.can(capability, { userId, orgId });
if (allowed) {
next();
} else {
res.status(403).json({
error: "Access denied",
message: `Capability '${capability}' not available`
});
}
} catch (error) {
// Handle Entitle API errors
console.error("Entitle evaluation error:", error);
res.status(500).json({ error: "Policy evaluation failed" });
}
};
};
// Use in routes
app.get('/api/export',
authenticate,
requireCapability('export-data'),
async (req, res) => {
// Your export logic
}
); Caching Strategy
The SDK includes short-lived in-memory caching (TTL-based) to reduce latency and API load. Cache keys are scoped to (principal, capability, context) tuples.
const entitle = new EntitleClient({
apiKey: process.env.ENTITLE_API_KEY,
cacheTTL: 60, // Cache decisions for 60 seconds
}); Error Handling
try {
const allowed = await entitle.can("premium-feature", context);
if (allowed) {
// Proceed
} else {
// Handle denial
}
} catch (error) {
if (error.code === 'TIMEOUT') {
// Entitle API timeout - decide on fail-open vs fail-closed
} else if (error.code === 'UNAUTHORIZED') {
// Invalid API key
} else {
// Other errors
}
} Shadow Mode (Zero-Risk Testing)
Shadow mode is critical for safe adoption. It allows you to test Entitle's decisions in production without enforcement risk.
Enable Shadow Mode
const entitle = new EntitleClient({
apiKey: process.env.ENTITLE_API_KEY,
shadowMode: true,
shadowDefault: 'allow', // or 'deny' - what to return while testing
});
// Your existing logic
const yourDecision = checkLocalPolicy(userId, capability);
// Entitle's decision (not enforced)
const entitleDecision = await entitle.can(capability, { userId, orgId });
// Log comparison for analysis
logger.info('Decision comparison', {
yours: yourDecision,
entitle: entitleDecision,
match: yourDecision === entitleDecision
});
// Enforce your existing logic (not Entitle's)
if (yourDecision) {
grantAccess();
} Progressive Adoption Path
Shadow Mode
Integrate SDK, call Entitle in parallel, don't enforce decisions yet. Build trust.
Partial Enforcement
Enforce Entitle decisions for non-critical capabilities. Keep local overrides.
Full Enforcement
Entitle becomes authoritative PDP. All decisions routed through Entitle.
Policy Management (Alpha)
In v1.0, policies are managed via an internal admin API. Web console UI is planned for v1.1+.
Policy Model (MVP)
{
"capability": "export-data",
"allowed_plans": ["pro", "enterprise"]
} Policy Operations
# Create policy
POST /v1/policies
{
"capability": "export-data",
"allowed_plans": ["pro", "enterprise"]
}
# List policies
GET /v1/policies
# Update policy
PUT /v1/policies/{id}
# Deactivate policy
DELETE /v1/policies/{id} Policy Versioning
All policy changes create immutable versions. Decisions include the policy_version
used for audit trails and rollback capability.
Enforcement Responsibility (Critical)
Entitle evaluates decisions. Your application enforces them. This separation is fundamental to the architecture.
What Entitle Does
- Evaluates policy based on principal, capability, and context
- Returns deterministic allow/deny decision
- Provides audit trail and decision reasoning
What Your Application Does
- Calls Entitle at decision boundaries
- Enforces the decision locally (grants or denies access)
- Handles errors if Entitle is unreachable
- Implements fail-open or fail-closed strategy
⚠️ Never Bypass Decisions
Do not implement logic that overrides Entitle's decisions based on business rules. If policy logic is wrong, fix the policy—don't bypass the PDP.
Failure Modes & Error Handling
Design your integration to handle scenarios where Entitle is temporarily unreachable.
Fail-Closed (Deny by Default)
try {
const allowed = await entitle.can(capability, context);
return allowed;
} catch (error) {
logger.error('Entitle unavailable, denying access', error);
return false; // Fail-closed
} Fail-Open (Allow by Default)
try {
const allowed = await entitle.can(capability, context);
return allowed;
} catch (error) {
logger.error('Entitle unavailable, allowing access', error);
return true; // Fail-open (use with caution)
} Recommended Strategy
- Critical capabilities: Fail-closed
- Non-critical capabilities: Fail-open with monitoring
- Always log failures and alert on elevated error rates
- Use SDK caching to reduce impact of transient failures
MVP Scope (v1.0) & Roadmap
Included in MVP
- Decision evaluation API (
/v1/evaluate) - Simple policy management (allow-list model)
- Node.js SDK with caching and shadow mode
- API key authentication
- Structured decision logging
- Hard tenant isolation
Deferred to v1.1+
- Entitlement snapshots (offline tolerance)
- Audit query APIs
- Python, Java, Go SDKs
- mTLS certificate authentication
- Admin web console
- Usage limits (advisory)
- Trial & grace period handling
- Rollout percentages & kill switches