import type { PrincipalResolution } from '@/lib/server/authz/principal'; export type ResourceAuthorizationAction = 'read' | 'write' | 'cancel' | 'resume' | 'delete'; export type ResourceOwnership = | { readonly state: 'owned'; readonly ownerPrincipalId: string } | { readonly state: 'guest-owned'; readonly guestPrincipalId: string } | { readonly state: 'public-read' } | { readonly state: 'legacy-unowned' } | { readonly state: 'unknown' }; export type ResourceAuthorizationDecision = | { readonly effect: 'allow'; readonly reason: 'owner_match' | 'guest_match' | 'public_read' | 'explicit_capability'; } | { readonly effect: 'deny'; readonly reason: 'unauthenticated' | 'owner_mismatch' | 'action_not_allowed'; } | { readonly effect: 'indeterminate'; readonly reason: 'resolver_unavailable' | 'owner_missing' | 'owner_unknown'; }; export interface ResourceAuthorizationInput { readonly principal: PrincipalResolution; readonly ownership: ResourceOwnership; readonly action: ResourceAuthorizationAction; /** * An exact capability which may override an owner mismatch. Principal kind * alone never grants elevated access. */ readonly overrideCapability?: string; } /** Pure ownership policy. It performs no authentication and no I/O. */ export function decideResourceAuthorization( input: ResourceAuthorizationInput, ): ResourceAuthorizationDecision { const { ownership, principal, action } = input; if (ownership.state === 'legacy-unowned') { return { effect: 'indeterminate', reason: 'owner_missing' }; } if ( ownership.state === 'unknown' || (ownership.state === 'owned' && ownership.ownerPrincipalId.trim().length === 0) || (ownership.state === 'guest-owned' && ownership.guestPrincipalId.trim().length === 0) ) { return { effect: 'indeterminate', reason: 'owner_unknown' }; } if (ownership.state === 'public-read') { return action === 'read' ? { effect: 'allow', reason: 'public_read' } : { effect: 'deny', reason: 'action_not_allowed' }; } if (principal.state === 'unavailable') { return { effect: 'indeterminate', reason: 'resolver_unavailable' }; } if (principal.state === 'anonymous') { return { effect: 'deny', reason: 'unauthenticated' }; } if ( ownership.state === 'owned' && (principal.principal.principalId === ownership.ownerPrincipalId || principal.principal.userId === ownership.ownerPrincipalId) ) { return { effect: 'allow', reason: 'owner_match' }; } if ( ownership.state === 'guest-owned' && principal.principal.kind === 'device' && principal.principal.principalId === ownership.guestPrincipalId ) { return { effect: 'allow', reason: 'guest_match' }; } if ( input.overrideCapability && principal.principal.capabilities.includes(input.overrideCapability) ) { return { effect: 'allow', reason: 'explicit_capability' }; } return { effect: 'deny', reason: 'owner_mismatch' }; } /** Future enforcement must fail closed for deny and indeterminate decisions. */ export function isResourceAuthorizationAllowed(decision: ResourceAuthorizationDecision): boolean { return decision.effect === 'allow'; }