Policy
A PolicySpec defines who can do what, when, and under what conditions. ContractSpec uses attribute-based access control (ABAC) to enforce policies across your entire application—from API endpoints to UI components.
Why policies matter
Traditional access control relies on roles (RBAC), which can become unwieldy as applications grow. ABAC is more flexible—it evaluates policies based on attributes of the user, resource, action, and context.
ContractSpec's policy engine ensures that access control is consistent across all surfaces. You don't have to remember to add authorization checks in every API endpoint or UI component—the Policy Decision Point enforces policies automatically.
Policy structure
A PolicySpec contains one or more rules. Each rule has:
- Effect – PERMIT, DENY, or REDACT
- Condition – A boolean expression that determines when the rule applies
- Scope – Which resources, actions, or fields the rule applies to
- Priority – Rules are evaluated in priority order; the first matching rule wins
Example PolicySpec
Here's a policy that controls access to customer data in TypeScript:
import { definePolicy } from '@lssm/lib.contracts';
export const CustomerDataAccess = definePolicy({
meta: {
name: 'customer.data.access',
version: 1,
},
rules: [
{
id: 'admin-full-access',
priority: 100,
effect: 'PERMIT',
condition: (ctx) => ctx.user.role === 'admin',
scope: {
resources: ['customer'],
actions: ['read', 'write', 'delete'],
},
},
{
id: 'sales-read-assigned',
priority: 200,
effect: 'PERMIT',
condition: (ctx) =>
ctx.user.role === 'sales' &&
ctx.resource.assignedTo === ctx.user.id,
scope: {
resources: ['customer'],
actions: ['read', 'write'],
},
},
{
id: 'support-read-redacted',
priority: 300,
effect: 'REDACT',
condition: (ctx) => ctx.user.role === 'support',
scope: {
resources: ['customer'],
actions: ['read'],
},
redactFields: ['creditCard', 'ssn', 'bankAccount'],
},
],
});Attributes
Policy conditions can reference attributes from four categories:
User attributes
user.id, user.role, user.groups, user.department, custom attributes
Resource attributes
resource.type, resource.owner, resource.sensitivity, custom attributes
Action attributes
action (read, write, delete, execute, export, etc.)
Context attributes
time.hour, time.dayOfWeek, request.ipAddress, request.userAgent
Data classification
You can tag fields with sensitivity levels in your CapabilitySpecs and DataViewSpecs:
fields:
- name: email
type: string
sensitivity: PII
- name: creditCard
type: string
sensitivity: PII
encrypted: true
- name: diagnosis
type: string
sensitivity: PHI
- name: salary
type: number
sensitivity: confidentialPolicies can then reference these tags to enforce blanket rules like "support staff cannot see PII" or "PHI can only be accessed from approved IP addresses."
Testing policies
ContractSpec provides tools for testing policies before deployment:
- Policy simulator – Test how policies evaluate for different users and scenarios
- Coverage analysis – Identify resources or actions that aren't covered by any policy
- Conflict detection – Find rules that might conflict or produce unexpected results
- Audit mode – Run policies in audit-only mode to see what would be blocked without actually blocking it
Best practices
- Start with a deny-by-default policy—explicitly permit what should be allowed.
- Use clear, descriptive rule IDs that explain what the rule does.
- Set priorities carefully to ensure rules are evaluated in the right order.
- Test policies thoroughly with realistic user scenarios before deploying.
- Monitor policy decisions in production using audit logs.
- Review and update policies regularly as your application and requirements evolve.