# JARVIS Module Contracts

**Phase:** 2A contract specification only  
**Purpose:** Define contracts precise enough to later generate Pydantic models and TypeScript types.

## Contract versioning

Current version: `jarvis.module_snapshot.v1`

Breaking changes require:

- version bump
- ADR or contract changelog
- example payload update
- contract tests update

## Enums

### ModuleId

```text
finance | health | autoshorts | system
```

### ModuleStatus

```text
ok | attention | degraded | offline
```

### Sensitivity

```text
public | internal | sensitive | critical
```

### DisplayPolicy

```text
hidden | summary | exact
```

### Severity

```text
info | success | warning | error | critical
```

### ActionMode

```text
link_only | read_only | preview_required | confirm_required | blocked_in_mvp
```

### SourceType

```text
api | sqlite_summary | filesystem_metadata | static_config | mock
```

## Models

Pseudo-TypeScript notation is used for readability. Python/Pydantic should mirror these fields.

### ModuleSnapshot

```ts
type ModuleSnapshot = {
  module_id: ModuleId
  title: string
  status: ModuleStatus
  sensitivity: Sensitivity
  display_policy: DisplayPolicy
  last_success_at: string | null
  last_attempt_at: string | null
  stale_after_seconds: number
  degraded_reason: string | null
  source_health: SourceHealth
  kpis: KpiItem[]
  attention_items: AttentionItem[]
  links: ActionDescriptor[]
  primary_action: ActionDescriptor | null
  contract_version: string
}
```

Rules:

- `kpis.length <= 3` for global module cards.
- `attention_items` can be more than 5 per module, but `OverviewResponse.attention_items` must be capped at 5 globally.
- `display_policy=exact` is forbidden for Health in MVP and forbidden for Finance global overview.

### SourceHealth

```ts
type SourceHealth = {
  reachable: boolean
  latency_ms: number | null
  source_type: SourceType
  version: string | null
  contract_version: string
  last_success_at: string | null
  last_error_redacted: string | null
  stale: boolean
}
```

Rules:

- `last_error_redacted` must not contain stack traces, file paths, secrets or raw domain values.

### KpiItem

```ts
type KpiItem = {
  key: string
  label: string
  value: string | number | boolean | null
  unit: string | null
  severity: Severity
  sensitivity: Sensitivity
  display_policy: DisplayPolicy
  help_text: string | null
}
```

Rules:

- Global Finance KPIs must not use exact amounts.
- Health KPIs must be counts/status only.

### AttentionItem

```ts
type AttentionItem = {
  id: string
  module_id: ModuleId
  title: string
  message: string
  severity: Severity
  sensitivity: Sensitivity
  created_at: string
  action: ActionDescriptor | null
  dedupe_key: string
}
```

Rules:

- Overview shows max 5 by severity/time.
- Message must be sanitized.

### ActionDescriptor

```ts
type ActionDescriptor = {
  label: string
  href: string | null
  mode: ActionMode
  sensitivity: Sensitivity
  blocked_reason: string | null
  preview_required: boolean
  confirm_required: boolean
  audit_required: boolean
}
```

Rules:

- MVP actions are `link_only`, `read_only`, or `blocked_in_mvp`.
- Any future mutation must have `preview_required=true`, `confirm_required=true`, `audit_required=true`.

### ActivityEvent

```ts
type ActivityEvent = {
  id: string
  module_id: ModuleId
  title: string
  message: string
  severity: Severity
  sensitivity: Sensitivity
  occurred_at: string
  source_type: SourceType
  redacted: boolean
}
```

### ApprovalItem

```ts
type ApprovalItem = {
  id: string
  module_id: ModuleId
  title: string
  status: "pending" | "blocked" | "approved" | "rejected"
  severity: Severity
  sensitivity: Sensitivity
  requested_at: string
  preview_action: ActionDescriptor
  confirm_action: ActionDescriptor
}
```

Rules:

- In MVP, approval examples may exist as mock data only.
- Real confirm actions remain blocked.

### ReportLink

```ts
type ReportLink = {
  id: string
  module_id: ModuleId
  title: string
  kind: "html" | "pdf" | "markdown" | "json" | "external"
  href: string | null
  sensitivity: Sensitivity
  display_policy: DisplayPolicy
  generated_at: string | null
  blocked_reason: string | null
}
```

Rules:

- Health report links are blocked by default.
- Finance report files are not global overview links.

### RedactionPolicy

```ts
type RedactionPolicy = {
  default_display_policy: DisplayPolicy
  allow_exact_finance_values: boolean
  allow_health_detail_links: boolean
  forbidden_fields: string[]
  log_forbidden_fields: string[]
  demo_mode: boolean
}
```

### ModuleRegistryEntry

```ts
type ModuleRegistryEntry = {
  module_id: ModuleId
  title: string
  enabled: boolean
  sensitivity: Sensitivity
  source_type: SourceType
  base_url_env: string | null
  legacy_url_env: string | null
  runtime_base_env: string | null
  contract_version: string
  default_display_policy: DisplayPolicy
  actions_enabled: boolean
  notes: string | null
}
```

### RuntimeConfig

```ts
type RuntimeConfig = {
  jarvis_env: "development" | "production"
  jarvis_demo_mode: boolean
  jarvis_public_base_url: string
  jarvis_gateway_host: string
  jarvis_gateway_port: number
  jarvis_dev_cors_origins: string[]
  finance_api_base_url: string | null
  finance_legacy_dashboard_url: string | null
  health_runtime_base: string | null
  health_legacy_dashboard_url: string | null
  autoshorts_api_base_url: string | null
  autoshorts_legacy_dashboard_url: string | null
  redaction_default_policy: DisplayPolicy
  allow_exact_finance_values: boolean
  allow_health_detail_links: boolean
}
```

### OverviewResponse

```ts
type OverviewResponse = {
  contract_version: string
  generated_at: string
  status: ModuleStatus
  modules: ModuleSnapshot[]
  attention_items: AttentionItem[]
  activity: ActivityEvent[]
  redaction_policy: RedactionPolicy
  errors: ErrorEnvelope[]
}
```

Rules:

- `modules.length <= 4` for MVP overview.
- `attention_items.length <= 5`.

### ErrorEnvelope

```ts
type ErrorEnvelope = {
  code: string
  message: string
  severity: Severity
  module_id: ModuleId | null
  retryable: boolean
  details_redacted: boolean
  occurred_at: string
}
```

## Contract examples

See `docs/contracts/examples/*.json`.
