Skip to content

client の API 通信・Server Action 境界を静的検査する #40

Description

@koh110

背景

AGENTS.md では client のデータアクセスについて、単なる実装スタイルではなく architecture rule が定義されている。

  • GET は Server Actions を利用し Result 型を返す
  • POST / PUT / DELETE は /proxy/api/ 経由の client-side function を利用する
  • useActionState / <form action> は利用しない
  • API error は extractErrorMessage(body) を単一入口にする
  • body.detail 等の response shape を呼び出し側で直接参照しない

これらが自然言語だけだと、画面追加時に別の通信パターンが混在しても検出できない。

目的

client の data access pattern を architecture contract として静的検査する。

実装案

AST / dependency rule を組み合わせて以下を検査する。

GET

  • client component から backend API を直接 fetch しない
  • GET 用 Server Action が project の Result 型契約に接続されていることを確認する
  • server-only module を client component から import しない

Mutation

  • POST / PUT / DELETE は project の proxy client 経由に限定する
  • /api/ への直接 fetch を禁止する
  • /proxy/api/ の共通実装を通す

Error handling

  • response body の .detail / .title 等への直接 access を禁止する
  • extractErrorMessage() を error message extraction の単一入口にする

注意

汎用 fetch() 自体を禁止すると外部 API / asset 等を誤検知するため、backend API の URL pattern や project wrapper に絞って判定する。

Acceptance Criteria

  • client component から backend GET API の直接呼び出しを検出できる
  • mutation の proxy bypass を検出できる
  • API error response shape の直接参照を検出できる
  • server-only dependency の client import を検出できる
  • 正常系・異常系 fixture がある
  • 機械化した通信規約を AGENTS.md から削減する

追加: server-only module boundary

Next.js の server/client boundary を明示的な architecture rule として扱う。

検査候補

  • *.server.ts / *.server.tsx は import 'server-only' を必須とする
  • server-only module から client component への依存を禁止する
  • 'use client' module から server-only module への import chain を禁止する
  • auth / API credential / server config 等を browser reachable graph から遮断する

単純なファイル名判定だけでなく、dependency graph で client entrypoint から server-only module への到達可能性も検査する。

Acceptance Criteria 追加

  • *.server.* で server-only marker の欠落を検出できる
  • client component から server-only module への依存を検出できる
  • transitive dependency 経由の server-only leakage も可能な範囲で検出する

設計補足: GET は実行コンテキストで経路を分ける

GET を一律に Server Action のみに限定しない。

重要なのは HTTP method ではなく どこから実行される request か で経路を分離すること。

Server-side initial data load

ページ初期描画や Server Component / Server Action 内で取得できるデータは、server-side API client から backend API を直接呼ぶ。

initial page load
      ↓
Server Component / Server Action
      ↓
server API client
      ↓
backend API

主な用途:

  • 初期表示
  • server-side rendering に必要なデータ
  • server-side redirect / authorization 判定と一緒に取得するデータ

Browser-driven request

browser interaction によって発生する request は GET を含め /proxy/api/ を利用できる。

browser interaction
      ↓
client API client
      ↓
same-origin /proxy/api/*
      ↓
server-side proxy
      ↓ inject Authorization
      ↓
backend API

主な用途:

  • pagination
  • infinite scroll
  • polling
  • refresh button
  • autocomplete / search
  • modal を開いた時の追加取得
  • client-side revalidation

したがって /proxy/api/ は GET / POST / PUT / DELETE 等を扱える設計を維持する。

禁止するもの

禁止対象は「browser GET」ではなく、browser から backend API への直接通信。

'use client'
    ↓
fetch(API_URI + '/api/...')

のように proxy を bypass し、browser が backend URI / Authorization token / backend-specific contract を直接扱う構造を禁止する。

静的検査の考え方

「初回GETか、interaction後のGETか」は AST だけでは完全には判定できないため、HTTP method ベースの禁止 rule にはしない。

機械的には以下を保証する。

  • client-reachable code から backend URI への direct fetch を禁止
  • browser-side backend request は client API wrapper / /proxy/api/ を経由
  • server-side code は server API client を利用可能
  • server-only credential / Authorization injection は proxy / server-side code に限定
  • client API wrapper と server API client の import boundary を分離

初期データを Server Action / Server Component で取得すべきかどうかの意味的判断は human-only guideline として残す。

Acceptance Criteria 追加

  • proxy の GET を正規の browser-side data access path として許可する
  • HTTP method だけを理由に proxy GET を禁止しない
  • client-reachable code から backend API への direct access を検出できる
  • server API client / browser proxy client の dependency boundary を検査できる
  • 初期取得と browser interaction の使い分けを architecture documentation に明記する

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions