<!-- canonical: https://docs.axelabs.ai/services/index/schema-catalog -->
<!-- source: content/services/index/schema-catalog.mdx -->

---
title: Schema 카탈로그
description: GET /index/schemas 가 노출하는 typed-fact 계약. 15 active (10 relational base + 5 judgment) + 6 phase-1 stub. frozen_enums_hash 로 contract 고정 (SCHEMA_CONTRACT_DRIFT gate). Blueprint artifact citation 의 index.* kind authority.
---

# Schema 카탈로그

## 한 줄 정의

index 가 자기 도메인에서 생산하는 typed-fact kind 의 SoT. `GET /index/schemas` endpoint 가 단일 envelope 으로 노출 — 이것이 schema 의 유일한 출처 (외부 schema registry 없음, MCP 가 권위). 같은 envelope 이 `mcp_schema` 테이블에도 mirror 되며 (`index register-schemas`), live 집계는 [현황 페이지](https://axe.axelabs.ai/index) 의 "스키마 계약" 섹션에서 확인.

코드 SoT = `src/mcp.rs` (Rust) 의 `schemas_envelope_base()` 리터럴 (relational base) + `judgment_schema_defs()` (judgment). 두 곳이 served `/index/schemas` 와 `mcp_schema` 레지스트리의 single source.

## 현재 카운트 (2026-06, live)

| 구분 | 수 | 비고 |
|---|---|---|
| **active** | **15** | 10 relational base + 5 judgment (D-index-45/49). `mcp_schema` 에 등록됨 |
| **phase-1 stub** | 6 | `status: phase1_backlog`, `version: 0.1-stub` — body 없는 roadmap placeholder. 레지스트리 미등록 |
| **total (envelope)** | 20 | served `/index/schemas` 의 `schemas[]` 길이 |

stub 이 `active` 로 graduate (real body + `N.0` version 획득) 하면 `register-schemas` 가 코드 변경 없이 자동 등록.

## Envelope 형식

```bash
curl -H "Authorization: Bearer $INDEX_MCP_TOKEN" \
  https://axe.axelabs.ai/index/schemas
```

응답 (요약):

```jsonc
{
  "version": "1.0",
  "service": "index",
  "schemas": [
    {
      "name": "index.deal",
      "version": "1.0",
      "status": "active",
      "description": "...",
      "fields": { "deal_code": { "type": "string", "required": true }, "...": "..." }
    }
    // ... 14 active + 6 stub
  ],
  "metadata": {
    "active_count": 14,
    "total_count": 20,
    "frozen_enums": { "instrument": [...], "path": [...], "scrub_kind": [...], "...": "..." },
    "frozen_enums_hash": "3b58b4b0...11f57f"
  }
}
```

- 인증: required (Bearer, Entra ID RS256)
- versioning: 각 body 의 `version` 필드. 표시는 string ("1.0"), `mcp_schema.version` PK 는 integer major ("1.0" → 1)
- envelope `version`: 응답 모양 변경 시에만 bump

## 14 active schemas

### A. Relational base (10) — financial_model 6-table + deal pipeline

deal 의 relational compute substrate. `propose_deal_closure` 가 atomic 으로 적재, `get_deal` / `get_exit_matrix` / `compute_outputs` / `query_irr` 가 읽음. 상세 = [financial-model](/services/index/financial-model).

#### 1. `index.target_company` (v1.0)

| field | type | notes |
|---|---|---|
| `legal_name` | string · required | 한글 정식 상호 |
| `brand_name` | string | 영문/한글 브랜드명 |
| `biz_no` | string | 사업자등록번호 `^\d{3}-\d{2}-\d{5}$` |
| `sector` | string | sector_framework code 참조 |
| `founding_date` | date | |
| `founders` | array | |
| `website` | uri | |

생성/읽기: `propose_deal_closure` · `get_deal`.

#### 2. `index.deal` (v1.0)

deal_code 가 stable identifier — UUIDv5 idempotency key 의 namespace.

| field | type | notes |
|---|---|---|
| `deal_code` | string · required | stable UI ID (예: Iippo / Sentry / Canopy) |
| `target_company_id` | uuid · required | |
| `stage` | enum | Pre-A · Series A · Series B · Series C · Bridge · Exit |

#### 3. `index.fund_investment` (v1.0)

deal × fund_entity × round 의 3-axis N:M ([D-index-5](/ops/decisions)). 1호 + 2호 동시 투자 시 각각 IRR 독립 산출. 상세 = [financial-model § fund_investment](/services/index/financial-model#fund_investment).

| field | type | notes |
|---|---|---|
| `deal_id` | uuid · required | |
| `fund_entity_id` | string · required | axe_ia_001 / axe_ia_002 등 |
| `round_label` | string · required | |
| `instrument` | enum · **frozen** | RCPS · BW · SAFE · 신주 · 보통주 ([D-index-15](/ops/decisions)) |
| `committed_krw` | number · required | |
| `invested_krw` | number · nullable | |
| `paid_date` | date · nullable | |
| `status` | enum · **frozen** | committed · paid · locked_in · written_off · partial_exited · exited |

#### 4. `index.financial_model` (v1.0)

6-table SoT 의 root (per-deal). `version` + `locked_at` + `source_xlsx_sha256` 가 immutable provenance.

| field | type | notes |
|---|---|---|
| `deal_id` | uuid · required | |
| `version` | integer · required | v(N) per ic skill |
| `time_axis_kind` | enum | annual · quarterly · monthly |
| `start_period` | date · required | |
| `horizon_periods` | integer · required | |
| `currency` | string | default KRW |
| `source_xlsx_sha256` | string · nullable | round-trip integrity |

#### 5. `index.financial_driver` (v1.0)

driver = formula DSL atom. DSL grammar = 10 operator (`+ - * / min max if sum avg lag growth`) — [D-index-15](/ops/decisions) immutable. 문법 = [financial-model § DSL](/services/index/financial-model#dsl-formula).

| field | type | notes |
|---|---|---|
| `code` | string · required | snake_case (예: gross_margin_terminal) |
| `kind` | enum · **frozen** | input · derived · output |
| `formula` | string · nullable | DSL — derived 만 required |
| `dependencies` | array | self-lag (`revenue[y-1]`) 는 cycle 미간주 |
| `units` | string | KRW · percent · multiple |
| `category` | string | revenue · cost · opex · capex · financing |

#### 6. `index.financial_scenario` (v1.0)

scenario = (base · mgmt · upside · downside) × probability. Σ probability = 1.0 ±0.02.

| field | type | notes |
|---|---|---|
| `code` | string · required | base · mgmt · upside · downside · custom |
| `kind` | enum | base · mgmt · upside · downside · stress |
| `probability` | number · required | 0~1, Σ = 1.0 |
| `name` · `description` | string | |

#### 7. `index.exit_matrix_leaf` (v1.0)

scenario × timing × path 의 joint probability leaf. 읽기 = `get_exit_matrix`.

| field | type | notes |
|---|---|---|
| `scenario_id` | uuid · required | |
| `timing` | string · required | 3y · 5y · 7y · never |
| `path` | enum · **frozen** | ma · ma_strategic · ipo · secondary · writedown · partial |
| `probability` | number · required | within-scenario, Σ = 1.0 |
| `axe_proceeds_krw` | number · nullable | fund_share proceeds |
| `recovery_rate` | number · nullable | writedown fallback |

#### 8. `index.financial_output` (v1.0)

`compute_outputs` / `query_irr` 의 결과. **Blueprint IC memo 가 가장 자주 cite** ("IRR" 의 출처).

| field | type | notes |
|---|---|---|
| `deal_code` | string · required | |
| `model_id` | uuid · required | |
| `irr_expected_cashflow` | number | **IRR(E[CF]) — 유일 canonical IRR** ([D-index-25](/ops/decisions)/[32](/ops/decisions); Σp·IRR 폐기) |
| `expected_moic` | number | E[MoM] |
| `prob_loss` | number | `P(MoM<1)` |
| `success_probability` | number | |
| `methodology` | string | default "IRR(E[CF]) canonical" |

#### 9. `index.financial_statement_line` (v1.0)

`compute_3fs` 의 IS/BS/CF typed line items (gross_profit / opex_total / ebit / pretax_income / tax_expense / net_income). Phase 0 = IS focus, BS/CF placeholder.

#### 10. `index.skill_resource` (v1.0)

`list_skills` / `get_skill_resource` 가 노출하는 skill resource fact (skill identifier + 파일 path + sha256). owner:index skill 의 read-path schema ([D-index-47](/ops/decisions) — skill ownership 의 byte 식별). MCP byte-delivery 가 아니라 식별/감사용 (실 분배는 mirror, [skill-ownership](/services/index/skill-ownership)).

---

### B. Judgment layer (4) — artifact-first ([D-index-45](/ops/decisions))

relational 값을 **지배하는 판단**을 typed fact 로 적재. SoT = `seed.yaml` 의 `judgment:` block + `seeds/_corpus.yaml` → `seed-ingest --emit-judgment` 로 파생 ([D-index-46](/ops/decisions) — hardcoded backfill 폐기). lifecycle propose→confirm, RLS owner_only, append-only `artifact_event`. 읽기 = `get_judgment_provenance` · `list_calibrations`. 현재 357 artifact / 23 deal (live 집계 = [현황](https://axe.axelabs.ai/index)).

> **링크는 일급 citation 이지 컬럼이 아님.** judgment artifact 는 두 종류의 citation 으로 연결된다:
> - `index_field` — relational field 로의 링크. ref = `{deal,field}` (예: `scenario:base:exit_multiple`)
> - `artifact_ref` — fact↔fact 링크. ref = `{artifact_id,relation}`, relation ∈ `calibrated_from` · `scrubbed_from` · `anchored_to` · `contradicts` (**frozen**)

#### 11. `index.assumption` (v1)

한 relational `field_ref` 를 지배하는 입력/파라미터 판단.

| field | type | notes |
|---|---|---|
| `field_ref` | string · required | relational target (예: `scenario:base:exit_multiple` · `output:irr_expected_cashflow` · `leaf:downside:axe_proceeds` · `scenario:downside:probability`) |
| `scope` | string · required | base · downside · weighted · deal-wide |
| `value` | number\|string · required | |
| `units` | string | multiple · percent · KRW · ratio |
| `rationale` | string · required | 왜 이 값인가 |
| `decision_ref` | string | D-index-N 참조 (optional) |

#### 12. `index.calibration` (v1)

SURFACE→CALIBRATED scrub ([D-index-24](/ops/decisions)/[26](/ops/decisions) 핵심). surface_value (deck/사업계획) 를 calibrated_value (research-calibrated) 로 조정한 판단.

| field | type | notes |
|---|---|---|
| `metric` | string · required | 조정 대상 (예: exit_multiple · revenue_ramp · downside_recovery) |
| `surface_value` | number\|string · required | 조정 전 표면값 (deck claim) |
| `calibrated_value` | number\|string · required | 채택값 |
| `scrub_kind` | enum · **frozen** | 7종 (아래 frozen-enum 표) |
| `scrub_reason` | string · required | |
| `decision_ref` | string · required | calibration 은 결정 추적 필수 |

artifact_ref `scrubbed_from`/`anchored_to` 로 comp/base_rate 에 링크, index_field 로 대상 relational field 에 링크.

#### 13. `index.comp` (v1)

Comparable — 한 지표의 비교가능 밴드. calibration 이 `artifact_ref(anchored_to)` 로 참조해 `multiple_anchor`/`fat_tail_comp_scrub` 을 정당화.

| field | type | notes |
|---|---|---|
| `name` | string · required | 예: commodity supplement exit multiple |
| `metric` | string · required | 예: ev_rev_multiple · psr · gross_margin |
| `value_low` | number · required | |
| `value_high` | number · required | |
| `sector` | string | |
| `source` | string · required | research 문서 / 시장 데이터 |

#### 14. `index.base_rate` (v1)

Base rate — 시나리오/wipeout 확률 산정 기준율 (예: 식품 5년 생존율 0.34). calibration / `scenario:*:probability` assumption 이 `artifact_ref(anchored_to)` 로 참조.

| field | type | notes |
|---|---|---|
| `name` | string · required | 예: food startup 5y survival |
| `value` | number · required | 0~1 비율 |
| `scope` | string · required | 예: genuine_wipeout · downside |
| `source` | string · required | |

#### 15. `index.deal_judgment` (v1)

**Dead-deal harvest** ([D-index-49](/ops/decisions)) — 한 deal 의 thesis-level **처분 JUDGMENT** ("왜 passed/lost/died" + durable lesson). claim(source-cited·live·갱신)과 달리 **author·불변·supersede** (재판단 = 새 artifact 가 prior 를 `artifact_ref(supersedes)`). `index_field{deal,"deal:disposition"}` 로 relational deal 에, `artifact_ref(anchored_to)` 로 backing comp/base_rate 에 링크. 읽기 = `query_dispositions`(verdict/sector/tag 횡단) · `get_deal_judgment`. seed `judgment.verdict:` block = SoT → `seed-ingest --emit-judgment` 파생.

| field | type | notes |
|---|---|---|
| `deal_code` | string · required | = para_anchor |
| `verdict` | enum · required · **frozen** | passed · lost · dead · invested · missed |
| `thesis` | string · required | one-line thesis-level 판단 (예: good company ≠ good deal) |
| `rationale` | array | 구체 사유 bullet |
| `lesson` | string · required | durable·재사용 lesson (예: field DD kills thesis) |
| `sector` | string · required | cross-deal rollup 용 (Pillar B sector Resource harvest 대상) |
| `tags` | array | open 패턴 vocabulary (예: good-company-not-good-deal · high-irr-not-go) |
| `decided_by` / `decided_at` | string | author stamp (누가 / 언제) |

## frozen-enum 계약 + `frozen_enums_hash` ([D-index-47](/ops/decisions) P1)

enum 값은 service code 에만 존재 — skill/producer 측에서 override 불가. 전체 frozen-enum set 의 deterministic sha256 = `frozen_enums_hash`, envelope `metadata` 에 publish. 현재 live:

```
frozen_enums_hash = 7895afeb4a135f38fb96e4dde239fc3981c790076ae7f7f638dc37d363132daa
```

envelope `metadata.frozen_enums` 의 키 (live):

| 키 | 값 |
|---|---|
| `instrument` | RCPS · BW · SAFE · 신주 · 보통주 |
| `path` (exit) | ma · ma_strategic · ipo · secondary · writedown · partial |
| `status` (fund_investment) | committed · paid · locked_in · written_off · partial_exited · exited |
| `statement` | (financial_statement_line statement code) |
| `is_line_code` | (income-statement line code) |
| `risk_kind` | (risk_alert stub kind) |
| `scrub_kind` | fat_tail_comp_scrub · genuine_wipeout · par_entry · dilution · over_pessimism_floor · ramp_haircut · multiple_anchor |
| `artifact_ref_relation` | calibrated_from · scrubbed_from · anchored_to · contradicts · supersedes |
| `verdict` (deal_judgment) | passed · lost · dead · invested · missed ([D-index-49](/ops/decisions)) |

### SCHEMA_CONTRACT_DRIFT gate

외부 propose caller (예: ic-push 경유 `propose_artifacts_from_ingest`) 는 마지막으로 본 `frozen_enums_hash` 를 `expected_frozen_enums_hash` 로 pin 할 수 있다. index live hash 와 불일치하면 propose 가 거부된다:

```jsonc
{ "error_code": "SCHEMA_CONTRACT_DRIFT", "message": "...(stale skill/contract — refresh against /index/schemas)" }
```

생략 시 게이트 비활성. propose 가 성공하면 `artifact_event.payload_after._provenance` 에 `skill` · `bundle_sha256` · `frozen_enums_hash` · `actor` · `surface` 가 stamp 된다 (P1 provenance). 상세 = [skill-ownership § P1](/services/index/skill-ownership).

## 6 phase-1 stubs (`status: phase1_backlog`)

body (`fields`) 없는 roadmap placeholder. `mcp_schema` 미등록 — graduate 시 자동 등록.

| stub | 예정 owner | 비고 |
|---|---|---|
| `index.dd_finding` | due-diligence skill | M7 후 |
| `index.ic_decision` | ic skill (`--push`) | atomic propose_deal_closure 흡수 vs 별도 propose 검토 |
| `index.portfolio_kpi` | pmc skill | quarterly_close 시 propose |
| `index.risk_alert` | pmc skill | red/yellow 조기 경보 |
| `index.valuation` | pmc skill | NAV / unrealized / realized |
| `index.lp_comm` | pmc skill | LP 보고 audit |

→ 이 6 stub 은 schema-catalog 의 미래 영역. 현행은 위 14 active 가 권위.

## Citation kinds (evidence)

artifact 의 evidence 는 typed citation. judgment-layer 의 일급 링크 (`index_field` · `artifact_ref`) 외에, extracted-fact 의 source 앵커:

| citation kind | ref 모양 | 의미 |
|---|---|---|
| `index_field` | `{deal,field}` | relational field 로의 judgment 링크 |
| `artifact_ref` | `{artifact_id,relation}` | fact↔fact 링크 (relation frozen 4종) |
| `xlsx_cell` | `{source_file,sheet,cell, sha256?}` | xlsx key_output 앵커 |
| `pdf_figure` | `{source_file,page, sha256?}` | pdf figure 앵커 |

### Evidence durability (sha256 content-anchor)

`xlsx_cell` / `pdf_figure` 의 ref 는 sha256 (cited 파일 bytes 의 hash) 를 PRIMARY 앵커로 carry — 파일이 이동·개명·삭제돼도 살아남는다. 추가 앵커: `drive_item_id` (OneDrive move-survivor) · `workspace_id` + `rel_path` · `marker`.

DURABLE := ref 에 non-null `sha256` OR `drive_item_id` OR (`workspace_id` AND `rel_path`). 아니면 FRAGILE (path-only). `verify_citations` 도구가 owner 의 citation 을 durable/fragile 로 집계 (현황 페이지에 durable% 노출). 상세 = evidence-durability v1, [/services/index § evidence-durability](/services/index#evidence-durability).

## Blueprint citation kind `index.*`

Blueprint artifact citation 의 `index.*` kind ([D-bp-artifact-3](/ops/decisions) 6 kind 에 7번째). IC memo 의 IRR 한 줄이 index 의 typed field 를 가리킴:

```jsonc
{
  "field": "irr_expected_cashflow",
  "citations": [{
    "kind": "index.financial_output",
    "deal_code": "Iippo",
    "model_id": "uuid-iippo-v8",
    "scenario_code": "weighted",
    "output_code": "irr_expected_cashflow"
  }]
}
```

Blueprint resolver 가 stable ID 로 실 value 를 fetch (`query_irr` MCP 호출) + cache. 상세 = [/architecture/artifacts § Citation 형태](/architecture/artifacts#citation-형태).

## Migration SQL

```
/Users/axe/index/migrations/
├── ..._shared_schema.sql       — entity / target_company / deal / fund_investment / sector_framework
├── ..._artifact_core.sql       — artifact / citation / artifact_event / mcp_schema (cortex 1:1 mirror)
├── ..._per_entity_template.sql — financial_model 6-table
├── ..._rls.sql                 — index_app role + FORCE RLS (owner_only)
├── ..._triggers.sql            — artifact_event audit + validate_driver_tree + exit_matrix_sanity
└── ..._judgment.sql            — judgment artifact kinds (D-index-45)
```

상세 = `/Users/axe/index/migrations/`.

## 관련 페이지

- [/services/index](/services/index) — 서비스 main (3-layer 모델 + MCP 도구 카탈로그)
- [/services/index/financial-model](/services/index/financial-model) — 6-table SoT 상세
- [현황 페이지](https://axe.axelabs.ai/index) — live 집계 (schema 수 · artifact · frozen_enums_hash)
- [/architecture/artifacts](/architecture/artifacts) — citation kind 7번째 등재
- [/ops/decisions D-index-45](/ops/decisions) — artifact-first judgment layer
- [/ops/decisions D-index-46](/ops/decisions) — seed=SoT (judgment 파생)
- [/ops/decisions D-index-47](/ops/decisions) — provenance + drift gate + skill ownership
