business-as-code
Version:
Primitives for expressing business logic and processes as code
585 lines • 15.3 kB
TypeScript
/**
* Organization Structure - Flows to FGA/RBAC
*
* Defines the complete organizational hierarchy:
*
* Organization
* └── Department
* └── Team
* └── Position (Role + Worker)
* └── Permissions (FGA/RBAC)
*
* This structure enables:
* - Hierarchical permission inheritance
* - Role-based task assignment
* - Approval chains based on org structure
* - Resource access control based on department/team
*
* @packageDocumentation
*/
import type { BusinessRole, TaskRoutingRule, WorkflowRole } from './roles.js';
/**
* Organization - top-level business entity
*
* @example
* ```ts
* const acme: Organization = {
* id: 'org_acme',
* name: 'Acme Corp',
* domain: 'acme.com',
* industry: 'technology',
*
* // Hierarchy
* departments: [engineering, sales, support],
*
* // Global settings
* settings: {
* defaultCurrency: 'USD',
* timezone: 'America/Los_Angeles',
* workWeek: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'],
* },
*
* // Resource hierarchy for FGA
* resourceHierarchy: {
* organization: { children: ['department', 'project', 'repository'] },
* department: { parent: 'organization', children: ['team'] },
* team: { parent: 'department', children: ['position'] },
* },
* }
* ```
*/
export interface Organization {
/** Unique identifier */
id: string;
/** Organization name */
name: string;
/** Primary domain */
domain?: string;
/** Legal name (if different) */
legalName?: string;
/** Industry/sector */
industry?: string;
/** Mission statement */
mission?: string;
/** Core values */
values?: string[];
/** Founded date */
foundedAt?: Date;
/** Headquarters location */
headquarters?: Address;
/** Organization settings */
settings?: OrganizationSettings;
/** Departments */
departments?: Department[];
/** Standalone teams (not in departments) */
teams?: Team[];
/** Organization-wide roles */
roles?: BusinessRole[];
/** Resource hierarchy for FGA */
resourceHierarchy?: ResourceHierarchy;
/** Global approval chains */
approvalChains?: ApprovalChain[];
/** Task routing rules */
routingRules?: TaskRoutingRule[];
/** Metadata */
metadata?: Record<string, unknown>;
}
/**
* Organization settings
*/
export interface OrganizationSettings {
/** Default currency */
defaultCurrency?: string;
/** Default timezone */
timezone?: string;
/** Work week days */
workWeek?: string[];
/** Business hours */
businessHours?: {
start: string;
end: string;
timezone?: string;
};
/** Fiscal year start month (1-12) */
fiscalYearStart?: number;
/** Default language */
language?: string;
/** Date format */
dateFormat?: string;
}
/**
* Address
*/
export interface Address {
street?: string;
city?: string;
state?: string;
postalCode?: string;
country?: string;
}
/**
* Department - major organizational division
*
* @example
* ```ts
* const engineering: Department = {
* id: 'dept_eng',
* name: 'Engineering',
* code: 'ENG',
*
* // Leadership
* head: { roleId: 'role_cto', positionId: 'pos_cto_jane' },
*
* // Teams
* teams: [platformTeam, productTeam, infraTeam],
*
* // Budget
* budget: {
* annual: 5000000,
* currency: 'USD',
* categories: {
* salaries: 3500000,
* tools: 200000,
* infrastructure: 800000,
* training: 100000,
* },
* },
*
* // FGA: Department-level permissions
* defaultPermissions: {
* repository: ['read'],
* project: ['read'],
* },
* }
* ```
*/
export interface Department {
/** Unique identifier */
id: string;
/** Department name */
name: string;
/** Short code (e.g., 'ENG', 'SALES') */
code?: string;
/** Description */
description?: string;
/** Department head position */
head?: PositionRef;
/** Parent department (for sub-departments) */
parentId?: string;
/** Teams within department */
teams?: Team[];
/** Department budget */
budget?: Budget;
/** Cost center code */
costCenter?: string;
/** Department goals */
goals?: string[];
/** Default permissions for department members */
defaultPermissions?: Record<string, string[]>;
/** Department-specific roles */
roles?: BusinessRole[];
/** Department-specific routing rules */
routingRules?: TaskRoutingRule[];
/** Metadata */
metadata?: Record<string, unknown>;
}
/**
* Team - working group within a department
*
* @example
* ```ts
* const platformTeam: Team = {
* id: 'team_platform',
* name: 'Platform Team',
* departmentId: 'dept_eng',
*
* // Leadership
* lead: { roleId: 'role_lead', positionId: 'pos_lead_bob' },
*
* // Members
* positions: [
* { id: 'pos_1', roleId: 'role_engineer', workerId: 'worker_alice' },
* { id: 'pos_2', roleId: 'role_engineer', workerId: 'worker_charlie' },
* { id: 'pos_3', roleId: 'role_engineer', workerId: null }, // Open position
* ],
*
* // Team resources (for FGA scoping)
* resources: {
* repositories: ['platform-core', 'platform-api'],
* projects: ['platform-v2'],
* },
*
* // Team-level permissions (inherited by members)
* defaultPermissions: {
* repository: ['read', 'edit', 'act:merge'],
* project: ['read', 'edit'],
* },
* }
* ```
*/
export interface Team {
/** Unique identifier */
id: string;
/** Team name */
name: string;
/** Parent department */
departmentId?: string;
/** Description */
description?: string;
/** Team lead position */
lead?: PositionRef;
/** Team positions */
positions?: Position[];
/** Team objectives */
objectives?: string[];
/** Team resources (for FGA scoping) */
resources?: TeamResources;
/** Team budget (if separate from department) */
budget?: Budget;
/** Default permissions for team members */
defaultPermissions?: Record<string, string[]>;
/** Workflow roles for this team */
workflowRoles?: WorkflowRole[];
/** Communication channels */
channels?: TeamChannels;
/** Metadata */
metadata?: Record<string, unknown>;
}
/**
* Team resources - scopes FGA permissions
*/
export interface TeamResources {
/** Owned repositories */
repositories?: string[];
/** Owned projects */
projects?: string[];
/** Owned products */
products?: string[];
/** Custom resource types */
[]: string[] | undefined;
}
/**
* Team communication channels
*/
export interface TeamChannels {
slack?: string;
teams?: string;
email?: string;
discord?: string;
}
/**
* Position - a role filled by a worker
*
* The position is the link between:
* - Business Role (responsibilities, permissions)
* - Worker (human or AI agent)
* - Location in org hierarchy (team → department → org)
*
* @example
* ```ts
* const seniorEngineerPosition: Position = {
* id: 'pos_se_123',
* title: 'Senior Software Engineer',
*
* // Role defines what this position can do
* roleId: 'role_senior_engineer',
*
* // Worker currently filling this position
* workerId: 'worker_alice',
* workerType: 'human',
*
* // Hierarchy
* teamId: 'team_platform',
* reportsTo: 'pos_lead_bob',
*
* // Position-specific permissions (added to role permissions)
* additionalPermissions: {
* 'repository:platform-core': ['manage'],
* },
*
* // Employment details
* startDate: new Date('2023-01-15'),
* status: 'active',
* }
* ```
*/
export interface Position {
/** Unique identifier */
id: string;
/** Position title */
title: string;
/** Business role this position requires */
roleId: string;
/** Worker filling this position (null = open position) */
workerId?: string | null;
/** Type of worker (human, agent, or either) */
workerType?: 'human' | 'agent' | 'any';
/** Team this position belongs to */
teamId?: string;
/** Position this reports to */
reportsTo?: string;
/** Direct reports (position IDs) */
directReports?: string[];
/** Position-specific additional permissions */
additionalPermissions?: Record<string, string[]>;
/** Start date */
startDate?: Date;
/** End date (for contractors/temporary) */
endDate?: Date;
/** Position status */
status?: 'active' | 'open' | 'on-leave' | 'terminated';
/** Full-time equivalent (1.0 = full-time) */
fte?: number;
/** Location */
location?: string;
/** Remote/hybrid/onsite */
workModel?: 'remote' | 'hybrid' | 'onsite';
/** Compensation */
compensation?: Compensation;
/** Metadata */
metadata?: Record<string, unknown>;
}
/**
* Position reference
*/
export interface PositionRef {
positionId?: string;
roleId?: string;
workerId?: string;
}
/**
* Compensation details
*/
export interface Compensation {
/** Base salary */
baseSalary?: number;
/** Currency */
currency?: string;
/** Pay frequency */
frequency?: 'hourly' | 'weekly' | 'biweekly' | 'monthly' | 'annual';
/** Bonus target percentage */
bonusTarget?: number;
/** Equity grants */
equity?: {
type: 'options' | 'rsu' | 'shares';
amount: number;
vestingSchedule?: string;
};
/** Band/level */
band?: string;
}
/**
* Budget allocation
*/
export interface Budget {
/** Total annual budget */
annual?: number;
/** Currency */
currency?: string;
/** Budget period */
period?: string;
/** Budget categories */
categories?: Record<string, number>;
/** Spent to date */
spent?: number;
/** Remaining */
remaining?: number;
}
/**
* Resource hierarchy definition for FGA
*
* Defines how resources relate to each other for permission inheritance.
*
* @example
* ```ts
* const hierarchy: ResourceHierarchy = {
* // Organization is root
* organization: {
* children: ['department', 'project', 'repository'],
* },
*
* // Department inherits from org
* department: {
* parent: 'organization',
* children: ['team'],
* },
*
* // Team inherits from department
* team: {
* parent: 'department',
* children: ['position'],
* },
*
* // Project can be org-level or team-level
* project: {
* parent: 'organization',
* alternateParents: ['team'],
* children: ['document', 'task'],
* },
*
* // Repository can be org-level or team-level
* repository: {
* parent: 'organization',
* alternateParents: ['team'],
* },
* }
* ```
*/
export interface ResourceHierarchy {
[]: ResourceHierarchyNode;
}
/**
* Node in resource hierarchy
*/
export interface ResourceHierarchyNode {
/** Primary parent resource type */
parent?: string;
/** Alternative parent types */
alternateParents?: string[];
/** Child resource types */
children?: string[];
/** Whether permissions cascade down */
inheritPermissions?: boolean;
/** Maximum depth (for nested resources) */
maxDepth?: number;
}
/**
* Approval chain - defines who approves what
*
* @example
* ```ts
* const expenseApprovalChain: ApprovalChain = {
* id: 'chain_expense',
* name: 'Expense Approval',
* type: 'expense',
*
* levels: [
* {
* threshold: 1000,
* approvers: [{ type: 'direct-manager' }],
* },
* {
* threshold: 5000,
* approvers: [
* { type: 'direct-manager' },
* { type: 'role', roleId: 'director' },
* ],
* },
* {
* threshold: 25000,
* approvers: [
* { type: 'direct-manager' },
* { type: 'role', roleId: 'vp' },
* { type: 'role', roleId: 'cfo' },
* ],
* },
* ],
*
* // Escalation settings
* escalation: {
* afterHours: 24,
* escalateTo: 'skip-level-manager',
* },
* }
* ```
*/
export interface ApprovalChain {
/** Chain identifier */
id: string;
/** Chain name */
name: string;
/** What type of requests this chain handles */
type: string;
/** Approval levels */
levels: ApprovalLevel[];
/** Escalation rules */
escalation?: EscalationRule;
/** Active/inactive */
active?: boolean;
/** Metadata */
metadata?: Record<string, unknown>;
}
/**
* Approval level within a chain
*/
export interface ApprovalLevel {
/** Threshold amount (requests above this need this level) */
threshold?: number;
/** Approvers at this level */
approvers: ApproverSpec[];
/** How many approvers needed */
requiredApprovals?: number;
/** Whether approvals at this level are sequential or parallel */
approvalMode?: 'sequential' | 'parallel' | 'any';
/** SLA for this level (hours) */
slaHours?: number;
}
/**
* Approver specification
*/
export interface ApproverSpec {
/** Approver type */
type: 'direct-manager' | 'skip-level-manager' | 'role' | 'position' | 'worker' | 'team';
/** Role ID (if type is 'role') */
roleId?: string;
/** Position ID (if type is 'position') */
positionId?: string;
/** Worker ID (if type is 'worker') */
workerId?: string;
/** Team ID (if type is 'team') */
teamId?: string;
}
/**
* Escalation rule
*/
export interface EscalationRule {
/** Hours before escalation */
afterHours: number;
/** Who to escalate to */
escalateTo: 'skip-level-manager' | 'department-head' | 'role' | 'position';
/** Role ID if escalating to role */
roleId?: string;
/** Position ID if escalating to position */
positionId?: string;
/** Maximum escalations */
maxEscalations?: number;
}
/**
* Resolved permissions for a worker
*
* Combines:
* - Organization-level defaults
* - Department-level permissions
* - Team-level permissions
* - Role permissions
* - Position-specific permissions
*/
export interface ResolvedPermissions {
/** Worker ID */
workerId: string;
/** Position ID */
positionId: string;
/** Effective permissions by resource type */
permissions: Record<string, string[]>;
/** Resource-specific permissions */
resourcePermissions: Record<string, Record<string, string[]>>;
/** Approval capabilities */
canApprove: string[];
/** Task handling capabilities */
canHandle: string[];
/** Inheritance chain (for debugging) */
inheritanceChain: string[];
}
/**
* Resolve permissions for a position in the org hierarchy
*/
export declare function resolvePermissions(org: Organization, positionId: string): ResolvedPermissions | null;
/**
* Get approval chain for a request
*/
export declare function getApprovalChainForRequest(org: Organization, requestType: string, amount?: number): ApproverSpec[];
/**
* Find manager for a position (follows reportsTo chain)
*/
export declare function findManager(org: Organization, positionId: string): Position | null;
//# sourceMappingURL=organization.d.ts.map