# task-2646 — CALLBACK_REGISTRATION_AUTHORITY_GATE

- Level: Lv.4 (시스템 callback registration path 단일화 + actual owner key gate + 4 source 교차)
- 담당: 회장 결정 후 dispatch · 별도 worktree task-2646-{bot}
- base: origin/main 최신
- 단일소스 spec: 본 task md (회장 verbatim 전체)
- 사고 박제 단일소스: `memory/feedback_callback_authority_actual_owner_key_260524.md`
- 회장 결정 (2026-05-24 verbatim): task-2644 / task-2645 결과 격차 = callback registration path 비표준화 증거.

## 결함명 (회장 verbatim)
`CALLBACK_REGISTRATION_AUTHORITY_NOT_ENFORCED`

## 목표 (회장 verbatim)
모든 callback 등록 경로를 단일 helper로 통합하고, actual schedule owner key가 ANU key인지 등록 직후 검증한다.

## 12 필수 구현 (회장 verbatim 1:1)
1. callback registration helper 단일화 (`utils/callback_registration.py`)
2. dispatch.py path와 direct cron path 모두 동일 helper 사용 (양 경로 결선 강제)
3. envelope collector_key와 actual schedule owner key **비교** (수동 비교 X · helper 내장)
4. actual owner key != ANU key (`c119085addb0f8b7`) → `FAIL_CLOSED`
5. self-key callback → `SELF_COLLECTOR_FORBIDDEN` (등록 시도 차단)
6. cron-list 단독 판단 **금지** (helper 내부에서 4 source 교차)
7. schedule_history + cron-history owner key + envelope + result artifact 4 source 교차확인
8. one-shot cron fire 후 cron-list 0이어도 callback missing 단정 금지 (schedule_history 사후 조회로 분리)
9. callback authority marker schema (`schemas/callback_authority_marker_v1.json`)
10. `NON_AUTHORITATIVE_SELF_COLLECTOR` marker 양식
11. `AUTHORITATIVE_CALLBACK_COLLECTOR_PROCESSED` marker 양식
12. 상태 enum 정의: `DISPATCH_SUBMITTED_UNVERIFIED` / `CALLBACK_MISSING` / `OWNER_KEY_MISMATCH` (+ 기존 AUTHORITATIVE / NON_AUTHORITATIVE / CALLBACK_PROMPT_TOO_LARGE)

## 8 필수 fixture (회장 verbatim 7 + 정정 1 — 2026-05-24)
1. **task-2644 dev1 self-key 9CAB9D33 → FAIL / NON_AUTHORITATIVE** (실 사건 재현)
2. **task-2645 ANU key EBEF96C8 → PASS / AUTHORITATIVE** (실 사건 재현)
3. envelope ANU key but actual owner self-key → `FAIL / OWNER_KEY_MISMATCH` (envelope-actual mismatch)
4. cron-list 0 but schedule_history exists → `PASS source check` (one-shot fired)
5. cron-list 0 and schedule_history absent → `CALLBACK_MISSING`
6. direct cron WITHOUT helper (raw self-key) → `FAIL / REGISTRATION_HELPER_BYPASSED`
7. dispatch.py path uses same helper → `PASS`
8. **★ direct cron WITH helper + actual owner key 검증 → PASS** (회장 verbatim 2026-05-24 정정 — direct cron 자체 금지 아님 · helper contract 명시 포함 시 허용)

## 4 source 교차확인 (helper 내부 의무)
| source | 조회 명령 / path | 의미 |
|---|---|---|
| schedule_history | `/home/jay/.cokacdir/schedule_history/<id>.log` | actual fire 기록 + `bot_key_verifier` sha256 |
| cron-history (owner key) | `cokacdir --cron-history <id> --key <key>` ANU key + suspect self-key 양쪽 조회 | owner key 검증 (access denied = 다른 key) |
| envelope | cron prompt 원문 | 명시된 collector_key 텍스트 |
| result artifact | result.json / report / ledger entry | 봇 자가 박제 (교차검증 대상) |

## state enum (12)
- 기존 4: `AUTHORITATIVE_CALLBACK_COLLECTOR_PROCESSED` · `NON_AUTHORITATIVE_SELF_COLLECTOR` · `CALLBACK_MISSING` · `CALLBACK_PROMPT_TOO_LARGE`
- 신규 3: `DISPATCH_SUBMITTED_UNVERIFIED` · `OWNER_KEY_MISMATCH` · `OWNER_KEY_VERIFIED`
- 추가 5: `REGISTRATION_HELPER_BYPASSED` · `SCHEDULE_HISTORY_PENDING` · `CRON_LIST_AUTODELETED_FIRED` · `RESULT_ARTIFACT_SELF_ATTESTED` · `SOURCE_CROSS_CHECK_PARTIAL`

## 자동 진행 허용
- callback_registration helper / 4 source cross-checker / state enum / fixture / regression 구현
- ANU-Codex loop 자동수렴
- 4 Track 병렬 fan-out 가능

## task-2646 완료 전 금지 (회장 verbatim 7)
- task-2644 authoritative acceptance 금지
- task-2644 재검증 금지 (task-2646 PASS 후)
- self-key callback 수용 금지
- cron-list 단독 판단 금지
- live settings/cokacdir 수정 금지
- BOT App token / chair_authorization / real auto-merge / PR #141 pilot 금지
- merge execution 금지

## expected_files (~22 file 추정)
- utils 2 (callback_registration.py + callback_authority_validator.py)
- dispatch.py 수정 (helper 호출 결선)
- schemas 2 (callback_authority_marker_v1.json + callback_state_enum_v1.json)
- fixtures 7 (회장 verbatim 7 fixture × evidence/expected/PROVENANCE)
- regression 7 (각 fixture × helper + 4 source cross-checker + state enum 통합)
- task md / report / done event / INDEX

## finalize 프로토콜 (★ BOT App token 부재 — 로컬 한정)
1. base = origin/main 최신 clean
2. 신규 helper + schema + fixture + regression PASS · 기존 baseline 유지
3. **로컬 commit 만** (push/PR/merge 금지)
4. `/home/jay/workspace/memory/events/task-2646.done` 생성
5. `/home/jay/workspace/memory/reports/task-2646.md` 보고서 작성
6. ANU normal callback cron 강제 등록:
   - collector key: c119085addb0f8b7 (ANU · ★ 본 task 자체 = registration helper 사용해서 self-test)
   - envelope UTF-8 ≤3900 bytes (wc -c)
   - canonical_root=/home/jay/workspace
   - REGISTERED + schedule_id non-null + DELIVERED + UNCONFIRMED
   - result.json 9 필드
7. validate_spawn_callback_contract self-check + new callback_registration helper self-test
8. executor 시작/종료 ts + 로컬 commit SHA 명기

## 회장 보고 형식 (10 필드 1:1)
- branch:
- commit:
- changed files count:
- callback registration helper:
- 4 source cross-check:
- authority states (12 enum):
- fixtures (7):
- regression coverage:
- live infra modified: (★ 0 보장)
- forbidden action count: (★ 0 보장)

## frozen anchor (회장 verbatim)
- ANCHOR-1: "envelope collector_key 텍스트가 ANU key여도 actual schedule owner key가 self-key면 FAIL"
- ANCHOR-2: "callback registration helper 단일화 · dispatch.py + direct cron 양 경로 결선"
- ANCHOR-3: "4 source 교차확인 (schedule_history + cron-history + envelope + result artifact)"
- ANCHOR-4: "one-shot cron fire 후 cron-list 0이어도 missing 단정 금지"
- ANCHOR-5: "self-key callback NON_AUTHORITATIVE · 삭제 금지 · 독립 재검증 대체"
- ANCHOR-6: "task-2644 9CAB9D33 self-key FAIL ↔ task-2645 EBEF96C8 ANU key PASS 실증 fixture 강제"
- ANCHOR-7: "task-2646 PASS 전까지 task-2644 재검증 금지"

## allowed_resources (본 task의 capability)

```yaml
allowed_resources:
  paths:
    - "utils/callback_registration.py"
    - "utils/callback_authority_validator.py"
    - "utils/callback_source_cross_checker.py"
    - "dispatch.py"
    - "schemas/callback_authority_marker_v1.json"
    - "schemas/callback_state_enum_v1.json"
    - "tests/fixtures/callback_authority_gate/**"
    - "tests/regression/callback_authority_gate/**"
    - "tests/test_callback_registration*.py"
    - "tests/test_callback_authority_validator*.py"
    - "tests/test_callback_source_cross_checker*.py"
    - "tests/test_callback_authority_gate_integration*.py"
    - "memory/tasks/task-2646.md"
    - "memory/reports/task-2646.md"
    - "memory/events/task-2646.done"
    - "INDEX.md"
  forbidden_paths:
    - "/home/jay/.claude/settings.json"
    - "/home/jay/.claude/settings.local.json"
    - "/usr/local/bin/cokacdir"
    - ".github/**"
    - "memory/events/*.cron-*"
    - "memory/tasks/task-2644*"
    - "memory/tasks/task-2645*"
    - "memory/tasks/task-2643*"
    - "memory/tasks/task-2641*"
    - "memory/tasks/task-2642*"
    - "memory/specs/system_anu_callback_collector_control_plane_spec_260524.md"
    - "memory/specs/system_real_merge_executor_wiring_spec_260523.md"
    - "scripts/finish-task.sh"
    - "utils/replacement_pr_runner.py"
    - "hooks/**"
    - "**/.env*"
    - "**/credentials*"
  commands:
    - "pytest"
    - "python3 -m py_compile"
    - "python3 -m json.tool"
    - "git status"
    - "git diff"
    - "git add"
    - "git commit"
    - "git log"
    - "git checkout"
    - "git branch"
    - "git worktree"
    - "sha256sum"
    - "wc"
    - "printf"
    - "ls"
    - "grep"
    - "find"
  merge_policy: "local_only"
  ttl_hours: 72
```

끝
