Skip to content

feat: routes --role server — axum·actix-web route-decl과 수확 지역 가림 수정 - #23

Merged
ictechgy merged 10 commits into
mainfrom
feature/server-routes
Sep 30, 2026
Merged

ictechgy merged 10 commits into
mainfrom
feature/server-routes

Conversation

@ictechgy

Copy link
Copy Markdown
Owner

요약

API 영향 프로그램 Phase 7 후속. rustograph routes --role server로 axum·actix-web 서버의 isthmus http route-decl 사실을 내고, 수확의 이름 해석 결함(지역 변수를 같은 이름의 모듈·fn으로 읽음)을 고친다.

routes --role server

  • axum 0.7·0.8 — dispatch: "specificity". 서빙되는 라우터(axum::serve·into_make_service)에서 route·nest(axum path_for_nested_route 결합)·merge·지역 let·재대입·라우터를 돌려주는 크레이트 함수를 정적으로 편다. 경로 문법은 cargo metadata가 고정한 버전으로 고른다(0.7 :id/*rest, 0.8 {id}/{*rest}/{{). matchit의 중간 파라미터 빈 값 매칭은 빈 값 변형으로 낸다.
  • actix-web 4 — dispatch: "registration-order". App마다 order.group, 리소스마다 order.index. 매크로(#[get]·#[route]·#[routes]), web::resource·web::scope·App::route·configure, 가드(narrowed), {id:\d+} → paramConstraints, {tail}*와 빈 꼬리 변형, NormalizePath 효과.
  • 핸들러 symbol.usr는 impact·reach와 같은 정점 ID(같은 syn 수확의 트리로 해석) — reach --roots-from routes.json이 그대로 받는다. 클로저는 감싸는 fn + missing-route-usrs:.
  • 확정하지 못한 것은 dynamic 사실이나 스코프 있는 route-coverage:·framework-provided-routes:·unresolved-route-prefix:로 낸다. 내기 전에 템플릿 문법·order·스코프를 소비자와 같은 검사로 확인한다.
  • 규칙마다 axum 0.7.9/0.8.9·matchit 0.7.3/0.8.4·actix-web 4.15.0·actix-router 0.5.4·codegen 4.4.0·tower-http 0.6.11 소스 줄 근거: docs/HTTP-ROUTES.md.
  • isthmus 공유 벡터를 76b6141에서 잠금 파일과 함께 벤더링(conformance/, conformance.lock). 생산자 사례 60건 통과(template.grammar·normalize·dispatch.validate·scope.validate), 나머지는 사유별 분류.

오라클 (experiments/routes-oracle/)

fixture의 같은 lib.rs를 crates.io의 진짜 axum 0.8.9·0.7.9·actix-web 4.15.0으로 컴파일해 프로세스 안에서 요청(oneshot·test::init_service). "사실만으로 isthmus 방식으로 고른 핸들러 = 실제 디스패치"를 사실·끝 슬래시·기대·음성 요청으로 본다.

fixture 정밀도 재현율 음성 끝 슬래시
axum 0.8.9 24/24 23/23 12/12 22/22
axum 0.7.9 14/14 11/11 6/6 13/13
actix-web 4.15.0 23/23 18/18 9/9 19/19

기록을 커밋하고 tests/routes.rs가 오프라인으로 지금 출력과 정확히 대조한다.

수확 수정 (harvest)

  • 지역 묶음(let·let-else·매개변수·클로저·match 팔·if/while let·for, 블록 안 fn 매개변수) 스코프 스택. 값 자리의 단일 식별자는 지역이 먼저, 값 자리의 모듈 해석은 버림(같은 경로의 fn·const·static은 남김), self 수신자.
  • 자기 분석 가짜 간선 109개 제거(모듈 references 100 + 지역명과 같은 fn 9), tests/fixture 8개. type 레벨 cycles: 수정 커밋에서 13 → 8(이 브랜치 끝 12 — 새 routes 모듈의 메서드→모듈 함수 투영 4개, 게이트 아님).

e2e (scratch, isthmus 76b6141 무패치 + schemagraph 703a21f)

합성 axum+sqlx 백엔드: route 선택 trace 4 chain 모두 route → 핸들러 → relation-use → 테이블. 경로 호출 hop은 direct, 메서드 호출 hop은 candidate(syn 이름 팬아웃 — 수확 수정과 무관, --semantic 필요). 수정 전 바이너리로는 지역 repo가 모듈 crate::repo로 읽혀 두 route가 audit_log에 direct로 닿는 거짓 hop 2개가 생겼고 수정 후 사라졌다.

리뷰

GLM 2라운드(비테스트 diff). 반영: 모듈과 이름을 공유하는 fn·블록 안 fn 매개변수, UTF-16 길이 상한, 클로저 계수, 비객체 스코프, 빈 값 변형이 같은 템플릿 정적 경로에 가려짐(오라클로 재현), MethodRouter::layer·변수 레이어의 정규화 오판, actix app = app.route(..) 재대입 누락, 함수에 넘긴 App 한계, 루트 밖 dynamic 앵커. 반박: 누락 모듈(패치 분할), 캐시 조기 반환(harvest()는 캐시를 읽지 않음), 리다댁션으로 깨진 상수, cargo metadata 한계 접두사(resolve 부재가 곧 버전 판정 불가).

검증

cargo test(+ --features semantic 47), clippy(CI와 같은 1.98.1) 경고 0, cargo fmt --check, 커버리지 91.9%(게이트 90), verify-cli-contract.sh OK(routes 종료 코드·계약 필드·usr가 reach root), 자기 분석 rules --strict 0 / cycles --level symbol --strict 0, isthmus 76b6141 check가 세 fixture 문서를 받음.

알려진 근사(전부 거짓 match 쪽)

axum 경로 우선 405 vs isthmus method 우선, actix 라우트 수준 method 가드(405)·스코프 포획·web::get()의 HEAD 미수용, 정규화 미들웨어가 닿지 않게 만든 선언을 strict로 냄, actix 매크로의 리소스 수준 method 가드에 소비자 route-decl-path-shadowed 경고 가능.

🤖 Generated with Claude Code

ictechgy and others added 10 commits September 30, 2026 11:12
본문의 단일 식별자 경로가 지역 변수여도 같은 이름의 크레이트 루트 모듈·함수로
해석돼 가짜 references 간선이 생겼다(`fn f(repo: &Repo) { repo.all() }` →
`f → crate::repo`). 순회는 그 모듈의 uses 간선을 따라 모듈이 import한 아이템
전부에 닿는 과대 근사가 됐다. 메서드 본문의 `self` 수신자도 같은 경로로 현재
모듈에 대한 references가 됐다.

- 매개변수·let(let-else 포함)·클로저 매개변수·match 팔·if/while let·for 패턴이
  묶는 이름을 어휘 스코프 스택(harvest::locals)으로 추적하고, 값 자리(표현식
  경로·호출 대상·포맷 캡처)의 단일 식별자는 지역이면 아이템을 찾지 않는다.
  초기식은 새 묶음을 못 보고(`let x = x()`는 fn 호출), 블록을 나가면 사라진다.
- 값 자리 해석 결과가 워크스페이스 모듈이면 버린다 — 모듈은 타입 이름공간에만
  있다. 외부 크레이트로 붕괴한 정점(`dep::f()`)은 모듈 표에 없어 그대로다.
- 대문자 식별자 패턴은 상수·유닛 배리언트 비교로 보고 묶지 않는다(명명 관례
  근사 — 소문자 상수 패턴은 간선 누락 쪽으로 틀린다).

자기 분석: 가짜 간선 109개 제거(모듈 references 100, 지역명과 같은 fn 참조 9),
type 레벨 cycles 13 → 8. tests/fixture는 8개 제거(루트 모듈 references 7, 매개변수
`t`가 모듈 `t`로 읽힌 1).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
isthmus http 도메인(76b6141부터 platform rust의 route-decl을 받음)에 Rust 서버 쪽 선언을
낸다. 핸들러 usr는 impact·reach와 같은 정점 ID라 isthmus trace가 route → 핸들러 →
relation-use → 테이블로 잇는다.

- axum 0.7·0.8: dispatch specificity. 서빙되는 라우터(axum::serve, into_make_service)에서
  route·nest(path_for_nested_route 결합)·merge·지역 let·재대입·라우터를 돌려주는 크레이트 함수를
  정적으로 편다. 경로 문법은 cargo metadata가 고정한 버전으로 고른다(0.7 `:id`·`*rest`,
  0.8 `{id}`·`{*rest}`·`{{`). matchit의 중간 파라미터 빈 값 매칭은 빈 값 변형으로 낸다.
- actix-web 4: dispatch registration-order. App마다 order group, 리소스마다 index. 매크로
  (#[get]·#[route]·#[routes]), web::resource·scope·App::route·configure, 가드(narrowed),
  `{id:\d+}` → paramConstraints, `{tail}*` catch-all과 빈 꼬리 변형, NormalizePath 효과.
- 확정하지 못한 것은 dynamic 사실이나 스코프 있는 route-coverage·framework-provided-routes
  한계로 낸다. 내기 전에 템플릿 문법·order·스코프를 소비자와 같은 검사로 확인한다.
- source::harvest_parts가 같은 syn 수확의 모듈 트리·AST를 넘긴다(정점 ID 규칙을 다시 만들지
  않는다).
- isthmus 공유 벡터를 76b6141에서 잠금 파일과 함께 벤더링하고, 스텁 의존성으로 버전만
  흉내 내는 합성 fixture 세 개(axum 0.8·0.7, actix-web 4)를 더한다.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
experiments/routes-oracle은 fixture의 같은 lib.rs를 crates.io의 진짜 axum 0.8.9·0.7.9·
actix-web 4.15.0으로 컴파일해(패키지 [lib] path) 프로세스 안에서 요청을 보낸다. 사실만으로
isthmus 방식(세그먼트·method·끝 슬래시·제약, 구체성 또는 등록 순서)으로 고른 핸들러가
프레임워크의 실제 디스패치와 같은지 사실 요청·끝 슬래시 요청·기대 요청·음성 요청으로 본다.
세 fixture 모두 정밀도·재현율·음성·끝 슬래시 100%이고 기록을 커밋한다.

tests/routes.rs는 벤더링 벡터의 sha256·잠금 일치, 생산자 사례 60건(template.grammar·
normalize·dispatch.validate·scope.validate), 모든 사례 분류, 지금 출력과 오라클 기록의 정확한
일치, 임시 크레이트로 정규화 레이어·미평가 조각·프레임워크 선택·actix 가드와 서비스·axum
메서드 라우터 변형·버전 밖 axum·루트 밖 라우터 중복을 확인한다.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
--role 필수·server만, 모르는 --framework·그래프 플래그·위치 인자 거부(2), 사실 0건 문서의
target http, platform·dispatch·route-decl 필드, 그리고 routes 문서의 핸들러 usr가 전부
reach root로 받아지는지(0) 빌드된 바이너리로 본다.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
docs/HTTP-ROUTES.md에 axum·matchit·actix-web·tower-http 소스 줄로 확인한 매칭 규칙(경로
문법·끝 슬래시·우선순위·등록 순서·nest·scope 결합·정규화 미들웨어), 사실 변환 방법, 한계와
스코프, 근사의 실패 방향(모두 거짓 match), 오라클 결과를 적는다. README 두 언어에 routes 절,
HANDOFF에 이번 세션(수확 수정 효과·e2e 결과 포함)을 더한다.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
GLM 리뷰 지적을 재현해 고친다.

- `mod util`과 `fn util`은 이름공간이 달라 공존한다. 값 자리 해석이 모듈 경로를 버리는
  규칙 때문에 `util()` 호출 간선이 사라졌다 — 모듈마다 값 아이템(fn·const·static) 이름을
  따로 두고, 같은 경로의 값 아이템이 있으면 그 해석을 남긴다.
- 블록 안 fn은 바깥 지역을 비운 채 방문해 자기 매개변수가 지역으로 잡히지 않았다 — 그
  fn의 매개변수로 첫 겹을 만든다.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
GLM 리뷰 지적 반영.

- order group 줄이기와 dynamic channel 원문 자르기를 문자 수가 아니라 UTF-16 코드 단위로
  한다 — BMP 밖 글자가 섞이면 256·2,048 상한을 넘어 자체 검사가 문서를 거부했다.
- 감싸는 정점을 못 찾은 클로저는 근사 usr 한계가 아니라 usr 없는 핸들러로 센다.
- scope_problem은 객체가 아닌 값을 거부한다(이전에는 통과로 읽혔다).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
GLM 리뷰(2차) 지적을 재현해 고친다.

- axum: 같은 앵커·템플릿의 진짜 선언이 있는 빈 값 변형을 뺀다. matchit은 정적 경로를 먼저
  고르고 경로가 맞으면 method가 달라도 405로 끝난다 — `/v{x}/status` GET과 `/v/status`
  POST에서 `GET /v/status`가 405임을 오라클로 확인하고 fixture·기록에 더했다.
- axum: NormalizePathLayer는 레이어가 서비스를 감싸는 모양(`Layer::layer(svc)`,
  ServiceBuilder `.service(svc)`, `NormalizePath::trim_trailing_slash(svc)`)일 때만 효과로
  본다. MethodRouter::layer 인자나 변수로 넘긴 레이어가 전 선언을 optional로 만들었다.
- axum: 루트에서 닿지 않은 라우터의 dynamic 선언은 base 앵커다.
- actix: 함수 최상위의 `let app = App::new()…`와 `app = app.route(..)` 재대입을 따라간다
  (재대입 등록이 한계 없이 빠졌다). 함수 인자로 넘긴 App은 route-coverage로 센다.
- 오라클 예측의 HEAD→GET은 axum에서만 쓴다(actix `web::get()`은 HEAD를 받지 않는다).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ictechgy
ictechgy merged commit b674287 into main Sep 30, 2026
1 check passed
@ictechgy
ictechgy deleted the feature/server-routes branch September 30, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant