// contracts §13 — Permission Contracts
// File: permission.ts — PathPolicy, PermissionRequestContext, PermissionAction,
//   PermissionGrantScope, PermissionDecision, PermissionRecordResult, PermissionEngine

import type { SessionID, TaskID, AgentID, EvidenceRefID } from './ids.js'
import type { AirError } from './error.js'

// Re-export PathPolicy and ToolPermissionSpec from tool.ts so they are also
// available from this module per the DD §3 file map (PathPolicy canonical
// assignment: permission.ts) and downstream import expectations.
export type { PathPolicy, ToolPermissionSpec } from './tool.js'

// =============================================================================
// §13 — Permission Contracts
// =============================================================================

/**
 * Context provided when the ToolRegistry requests a permission evaluation.
 * Constructed from ToolExecutionContext + ToolDefinition.permissions + input
 * paths/commands per DD §9.1.
 */
export interface PermissionRequestContext {
  session_id: SessionID
  task_id?: TaskID
  agent_id?: AgentID
  tool_name?: string
  command?: string
  paths?: string[]
  network?: boolean
  requested_action: string
  reason: string
}

/**
 * Actions the PermissionEngine can return.
 * ToolRegistry.call branches on these per DD §9.3:
 *
 *   allow             — execute; create backup first if backup_required
 *   announce_then_run — emit visible notice, then execute unless interrupted;
 *                        bounded by grant_scope
 *   ask_user          — suspend; emit permission.prompt.requested;
 *                        resume on permission.prompt.resolved
 *   deny              — do not execute; return ToolResultEnvelope{status:"error"};
 *                        caller may pick safe path
 *   block             — return blocked outcome → task.blocked upstream
 *   refuse            — return AirError{kind:"policy_error"}; no execution
 */
export type PermissionAction =
  | 'allow'
  | 'announce_then_run'
  | 'ask_user'
  | 'deny'
  | 'block'
  | 'refuse'

/**
 * Scope of a permission grant. Determines how long the granted action
 * remains valid before re-evaluation is required.
 *
 *   none    — no grant (decision is informational only)
 *   once    — valid for this single invocation
 *   session — valid for the remainder of the session
 *   project — valid across sessions for this project
 *   global  — valid across all projects for this user
 */
export type PermissionGrantScope =
  | 'none'
  | 'once'
  | 'session'
  | 'project'
  | 'global'

/**
 * Risk levels assigned by the PermissionEngine during evaluation.
 * Used by downstream branching logic and UI presentation.
 */
export type PermissionRiskLevel = 'low' | 'medium' | 'high' | 'critical'

/**
 * Decision returned by PermissionEngine.evaluate.
 * Matches DD §22.1 specification and DD §9.3 branching table.
 *
 * Layered evaluation order (contracts §13, runtime-semantics §8, overview §12):
 *   1. tool capability declaration
 *   2. permission profile (permission_template)
 *   3. TaskSpec scope allowed/denied paths
 *   4. path/command/network risk classification (PathClassifier + CommandRiskAnalyzer)
 *   5. credential/system-sensitive override
 *   6. user prompt workflow if required
 */
export interface PermissionDecision {
  action: PermissionAction
  grant_scope: PermissionGrantScope
  risk_level: PermissionRiskLevel
  reason: string
  required_confirmation?: boolean
  backup_required?: boolean
  evidence_ref_ids?: EvidenceRefID[]
}

/**
 * Result of recording a permission decision.
 * PermissionEngine.record writes a permission.decision.recorded durable event
 * and returns this result; on write failure it returns {ok:false, error}.
 */
export interface PermissionRecordResult {
  ok: boolean
  error?: AirError
}

/**
 * Core permission evaluation engine interface.
 * Implements contracts §13, referenced by ToolRegistry (DD §9.1, §9.3).
 *
 * Invariants (DD §9.2):
 *   - project-level allow never overrides task scope
 *   - credential/system-sensitive overrides broad allows
 *   - paths normalized via realpath before prefix checks
 *   - .git/ internals protected
 */
export interface PermissionEngine {
  evaluate(context: PermissionRequestContext): Promise<PermissionDecision>
  record(decision: PermissionDecision, context: PermissionRequestContext): Promise<PermissionRecordResult>
}