実装学習記事全11節Build

画面から提出操作を送り、処理側で本人確認・権限判定を行う一巡を動かす

この記事で身につくこと画面と処理の間の通信、データ形式、連携先の仕様、待ち時間と失敗を、提出操作の一巡で説明できる。

記事内目次(21項目)
この記事の管理情報(該当工程・関連要件・成果物の閲覧と保存・実行記録)
記事ID
08-03
該当工程
08-03 画面・処理・外部機能をつなぐ(関連:08-02、05-03、00-01、08-04、09-03)
関連要件
REQ-002、REQ-003
到達目標
画面と処理の間の通信、データ形式、連携先の仕様、待ち時間と失敗を、提出操作の一巡で説明できる
主要な成果物
確認環境と検証状況
本文のコードは examples/08-03-integration-log/ を正本とし、Claude Codeが2026-09-20にローカル通信で実際に実行して stdout・stderr・終了コードを記録済み(macOS 26.6.2、Node.js v24.18.0)。Remediation Phase 1で、正本と一致していなかった掲載コード・掲載出力を正本の実測に置き換え、08-02の保存処理を実際に呼ぶ形に改めた。人による実読・内容確認は未実施。
未検証の範囲
複数の利用者が同時にアクセスする場合の動作、外部ネットワークを介した通信の場合の遅延・失敗パターンは、この記事の時点では確認していない。
実行記録

正本の原稿にある管理表(記事ID・先に読むと理解しやすい記事・成果物パス・最終更新日など)は、この下の本文冒頭に「原稿の管理表」として開閉できる形で残しています。

原稿の管理表(13項目:記事ID・カテゴリ・要件ID・先に読むと理解しやすい記事・成果物パス・対象ツール・検証状況・最終更新日など)
管理項目内容
記事ID08-03
主な中カテゴリ08-03 画面・処理・外部機能をつなぐ
関連中カテゴリ08-02、05-03、00-01、08-04、09-03
関連要件IDREQ-002、REQ-003
先に読むと理解しやすい記事08-02(入力・計算・保存をつなぐ)を読んでいると理解しやすい。未読でも本文で必要な内容は説明する
到達目標画面と処理の間の通信、データ形式、連携先の仕様、待ち時間と失敗を、提出操作の一巡で説明できる
3層の配置理解する=第3〜4節/作って確かめる=第5〜7節/設計を判断する=第8節
成果物パスtemplates/08-03-integration-log_template.md、templates/08-03-integration-log_example.md、examples/08-03-integration-log/(server.js、client.js、client-fail.js、storage.js)、evidence_public/remediation1-2026-09-20/08-03/run_log.md
出典第11節参照
対象ツール・バージョン教材演習用にNode.js v24.18.0(node:http・node:fs・node:path のみ使用、追加のパッケージは導入していない)
検証状況本文のコードは examples/08-03-integration-log/ を正本とし、Claude Codeが2026-09-20にローカル通信で実際に実行して stdout・stderr・終了コードを記録済み(第7節、evidence_public/remediation1-2026-09-20/08-03/run_log.md)。第5.4節の指示文は説明用の例であり、実際にAIへ送信・観測した記録ではない。人による実読・内容確認は未実施
残課題第11節参照
最終更新日2026-09-20(新規作成。同日、Remediation Phase 1:掲載コードを examples/ の正本と完全一致させ、08-02の保存処理を実際に使う形に改め、実行結果を正本の実測に置き換えた。同日、Phase 5B-2B:読む順路・第4節の判断項目・第5.4節「AIに連携処理を頼む」・第5.5節のレビュー観点・CHECKLIST・記事間の参照を追加。コード・実行結果・実行記録は不変)

この記事の会社・人物・データはすべて架空の設定です。実在する会社や案件とは関係ありません。本文のコードは examples/08-03-integration-log/ の正本と同じもので、実行結果は2026-09-20にローカル環境(localhost)で実際に実行して記録したものです(第7節、実行記録は第9節)。本人確認は固定値で代用しており、実際の認証機能ではありません。

この記事は何の話か。画面から「提出」操作を送り、処理側で本人確認(固定値で代用)・権限判定(自分の依頼か)・状態の確認を行い、08-02で作った保存処理で保存してから結果を画面に返す一巡を、実際にローカルの通信で動かす話です。

なぜ必要か。画面側だけで権限を確認しても、直接処理側にリクエストを送られた場合には対応できません(04-02で扱った内容)。処理側でも権限を確認する実装が必要です。

この記事を読むとできるようになること。

  • 画面と処理の間の通信、データ形式、待ち時間と失敗を、提出操作の一巡で説明できる
  • 提出操作の一巡を実装し、通信内容と結果を実行記録に残せる
  • 許可判定を処理側でも行う理由と、連携の失敗時の扱いを判断できる

読む順路。この記事は3つの深さで読めます。全部を順に読む必要はありません。

  • 基本だけ理解する:第1節→第3節(一巡の流れと誤解)→第4節(判断すること)→第5.2節の「入力→判断・処理→出力→失敗時」の表→第6節の連携経路の表→第7節の照合表→第9節。コードを読まなくても、処理側が何を確かめてから保存するか、失敗したときに画面側が何を受け取るかが分かります。
  • 作って確かめる:上に加えて第5.2〜5.3節(サーバーと画面側のコード)→第5.4節(AIに頼む:渡す情報と指示文)→第5.5節(初稿のレビュー)→第6節(実行結果と保存先の中身)。
  • 設計判断を深める:上に加えて第8節(判定を処理側で行う理由、失敗時の扱いの比較、適用限界)。

1. 今回の業務課題と完成するもの

この記事でやることは、画面(に見立てたクライアント)から「提出」操作を送り、処理側(サーバー)で本人確認・権限判定・状態の確認を行い、08-02の保存処理(storage.js)で保存してから結果を画面に返す一巡を実装し、通信内容と実行結果を記録することです。

08-02では保存処理を作りましたが、それを画面からの操作として送受信する部分はまだ扱っていませんでした。この記事では、その保存処理を処理側(サーバー)から実際に呼び出してつなぎます。

この記事を読み終えると、次のものが手元にできます。

  • 処理側・画面側の最小コードと、08-02の保存処理のコピー(examples/08-03-integration-log/)、実行記録
  • 連携処理・実行記録(連携の経路、送る内容、受け取る内容、待ち時間、失敗時の動作、代用した箇所)

2. 前提知識と読む順路

この記事で使う言葉を先に説明します。

HTTP

一言でいうと、画面(クライアント)と処理(サーバー)が情報をやり取りするための、広く使われる約束事です。

API(連携の約束)

一言でいうと、どのURLに、どんな形式でデータを送れば、何が返ってくるかという約束です。この記事では「POST /submit」というAPIを作ります。

待ち時間

一言でいうと、リクエストを送ってから応答が返るまでの時間です。

これがないと、画面と処理がどうやってつながっているかが分からず、失敗した場合にどこで問題が起きたかも分かりません。

読む順路:保存処理は08-02、権限表は05-03、状態遷移表は05-02、5つの登場人物は00-01が該当します。この記事の連携処理は、08-04(エラー処理と保守しやすさを整える)、09-03(例外・権限・同時操作・負荷を確認する)で使います。

3. 理解する:提出操作の一巡

3.1 一巡の流れ

00-01で見た見取り図のとおり、画面→通信→処理→保存先→応答という流れになります。この記事では、処理側が本人確認・権限判定・状態の確認を行い、保存先(08-02の storage.js)に書き込んでから応答を返すところまでを実装します。「保存先」の登場人物を省いてしまうと、応答が「ok」でも実際には何も保存されていない、という一巡になってしまいます。

「応答」の前に、保存までつなぐ。画面から提出:操作の情報を通信で送る。処理側で確認:本人・権限・状態を確かめる。保存先へ書き込む:依頼の状態と履歴を扱う。応答を返す:保存を伴う一巡として確かめる。説明図。実装・未検証の範囲は本文で確認。

3.2 よくある誤解

「画面で入力を検証すれば、処理側の検証は不要」。処理側に直接リクエストが送られた場合、画面側の検証は効きません。処理側でも必ず検証します(04-02・05-03で扱った考え方)。

「本人確認は難しいので、最初から本物の仕組みを作る必要がある」。この記事では、固定値による代用で仕組みの流れを確認し、実際の認証は別の記事・工程で扱います(設計書5.5)。

4. 判断すること

画面と処理をつなぐときに人が判断することは、次の5つです。

判断することなぜ判断が必要か仮置きしてよいか間違えた場合の影響
処理側で何を確かめてから保存するか(本人確認・権限・状態)画面側の確認は、画面を通らない操作には効かない(第3.2節、04-02)。確かめる条件は05-03の権限表と05-02の状態遷移表から来る不可。設計にある条件を減らさない直接送られた要求で、他人の依頼を提出できる。提出済みをもう一度提出して履歴が二重になる
判定に使う情報を、画面から送られた内容で信用するか、保存先から読み直すか画面が送る requestId 以外(依頼者が誰か、今の状態)を画面の申告で信用すると、改ざんされた要求を止められない不可。依頼者と状態は保存先から読む(第5.2節の手順2・3)「自分の依頼です」と申告した要求を通してしまう
本人確認をどこまで作るか実際の認証は別の工程(設計書5.5)。この記事で本物を作ると範囲が広がりすぎる可(固定値の対応表で代用し、代用であることを明記する)代用を本物と誤解し、認証が済んだものとして次工程へ渡す
失敗をどう返すか(状態コードと文言)画面側が次の操作を選べる文言(04-04)と、内部情報を出さないこと可(この記事は401/403/409と利用者向けの文言。通信自体の失敗は画面側が ECONNREFUSED を受け取る)内部のエラーがそのまま画面に出る。失敗の種類が区別できず、利用者が何をすればよいか分からない
実行結果をどこまで載せ、変動する値をどう扱うかwaitMs や at は実行のたびに変わる。変わる値を固定値のように載せると再現できない不可。全文を載せ、変動する値はその旨を明記する読者が再現して値が違い、記事の出力を疑う

勝手に決めてはいけないこと:05-03の権限表にない判定条件を、この記事で追加しません。固定値による本人確認を、実際の認証機能であるかのように書きません。画面側の確認だけで済ませる設計にしません。

AIに任せる範囲:サーバーと画面側のコードの下書き、実行して出力をそのまま返すこと、保存先の中身の表示はAIに任せられます。任せてはいけないのは、処理側で確かめる条件を決めること、判定に使う情報を保存先から読み直す設計にすること、代用(固定値の本人確認)と本物を区別して書くこと、そして初稿が「08-02の保存処理を本当に呼んでいるか」の確認です(第5.5節)。

5. 作って確かめる:処理側・画面側の一巡を実装する

5.1 準備

08-02の保存処理(storage.js)、05-03の権限表、05-02の状態遷移表(提出できるのは「下書き」「差戻し」のときだけ)を用意します。

examples/08-03-integration-log/storage.js は、08-02の examples/08-02-storage-check/storage.js と同じ保存処理のコピーです(先頭に「コピーである」注記を1行足したほかは同じ内容)。配布したときに同じフォルダだけで動くように置いています。この記事ではその中身は再掲せず、createRequest(依頼を下書きとして保存)と submitRequest(状態を提出済みに変え、履歴を1件足して1回の書き込みで保存)、loadDb(読み出し)を呼びます。

5.2 処理側(サーバー)のコード

// 教材演習用:処理側の最小サーバー(node:httpのみ使用)。
// 「提出」操作を受け取り、本人確認(固定値で代用)・権限判定・状態の確認を行い、
// 08-02の保存処理(storage.js)で保存してから応答を返す。
const http = require("node:http");
const fs = require("node:fs");
const { createRequest, submitRequest, loadDb, DB_FILE } = require("./storage.js");

// 本人確認は固定値で代用(実際の認証機能ではない。05-03参照)
const FIXED_USERS = { "u-sato": "佐藤", "u-suzuki": "鈴木" };

// 起動時に演習用データを初期化し、08-02の createRequest で依頼1件(下書き)を保存する
if (fs.existsSync(DB_FILE)) fs.unlinkSync(DB_FILE);
createRequest({ id: "REQ-0001", requester: "u-sato", title: "会議室の予約", content: "9/25 10時から", approver: "u-suzuki" });

function send(res, status, body) {
  res.writeHead(status, { "Content-Type": "application/json" });
  res.end(JSON.stringify(body));
}

const server = http.createServer((req, res) => {
  if (req.method !== "POST" || req.url !== "/submit") return send(res, 404, { error: "not found" });
  let body = "";
  req.on("data", (chunk) => (body += chunk));
  req.on("end", () => {
    const input = JSON.parse(body);
    console.log("受け取った内容:", input);
    // 1. 本人確認(固定値で代用)
    if (!FIXED_USERS[input.userId]) return send(res, 401, { error: "本人確認に失敗しました(固定値と一致しない)" });
    // 2. 権限判定:自分の依頼だけ提出できる(保存先から読み出して判定する)
    const target = loadDb().requests.find((r) => r.id === input.requestId);
    if (!target || target.requester !== input.userId) return send(res, 403, { error: "権限がありません(自分の依頼ではない)" });
    // 3. 状態の確認:提出できるのは「下書き」「差戻し」のときだけ(05-02の状態遷移表)
    if (target.state !== "下書き" && target.state !== "差戻し") {
      return send(res, 409, { error: `状態が「${target.state}」のため提出できません` });
    }
    // 4. 保存:08-02の submitRequest(状態変更と履歴追加を1回の書き込みで保存)
    const db = submitRequest(input.requestId, input.userId);
    const saved = db.requests.find((r) => r.id === input.requestId);
    return send(res, 200, { result: "ok", state: saved.state, historyCount: db.history.length });
  });
});
server.listen(8931, () => console.log("処理側サーバーが起動しました: http://localhost:8931"));

「入力→判断・処理→出力→失敗時」の対応:

段階内容
入力POST /submit の本文 { userId, requestId }
判断・処理1. 本人確認(固定値の対応表) → 2. 権限判定(保存先から依頼を読み出し、依頼者が本人か) → 3. 状態の確認(下書き・差戻しのときだけ提出できる) → 4. 08-02の submitRequest で保存
出力200 と { result: "ok", state, historyCount }。historyCount は保存後の履歴件数で、保存先が実際に変わったことの手がかり
失敗時本人確認の失敗は 401、権限なしは 403、状態が合わないときは 409 を、利用者向けの文言(04-04)で返す。保存先は変えない

5.3 画面側(クライアント)のコード

// 教材演習用:画面側(クライアント)に見立てた最小コード(node:httpのみ使用)。
// 「提出」操作を処理側へ送り、応答(状態コード・本文)と待ち時間を記録する。
const http = require("node:http");

function post(path, data) {
  return new Promise((resolve) => {
    const body = JSON.stringify(data);
    const start = Date.now();
    const req = http.request(
      { hostname: "localhost", port: 8931, path, method: "POST", headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) } },
      (res) => {
        let responseBody = "";
        res.on("data", (c) => (responseBody += c));
        res.on("end", () => resolve({ status: res.statusCode, body: JSON.parse(responseBody), waitMs: Date.now() - start }));
      }
    );
    req.on("error", (e) => resolve({ error: e.message }));
    req.write(body);
    req.end();
  });
}

async function main() {
  console.log("=== 1. 正常な提出(本人・自分の依頼・下書き) ===");
  console.log(await post("/submit", { userId: "u-sato", requestId: "REQ-0001" }));
  console.log("=== 2. 本人確認に失敗する場合(固定値と一致しないID) ===");
  console.log(await post("/submit", { userId: "u-unknown", requestId: "REQ-0001" }));
  console.log("=== 3. 権限がない場合(他人の依頼を提出しようとする) ===");
  console.log(await post("/submit", { userId: "u-suzuki", requestId: "REQ-0001" }));
  console.log("=== 4. 状態が合わない場合(提出済みの依頼をもう一度提出する) ===");
  console.log(await post("/submit", { userId: "u-sato", requestId: "REQ-0001" }));
}
main();

サーバーが動いていないときの通信失敗を確かめる最小コードです(client-fail.js)。

// 教材演習用:サーバーが動いていない場合の通信失敗を確認する最小コード。
const http = require("node:http");
const req = http.request({ hostname: "localhost", port: 8931, path: "/submit", method: "POST" }, () => {});
req.on("error", (e) => console.log("通信失敗:", e.code));
req.end();

5.4 AIに連携処理を頼む

サーバーと画面側のコードは、AIに書かせる想定です。渡す情報と渡さない情報を先に決めます。

渡す情報内容渡さない情報と理由
目的と完成条件画面から POST /submit で提出を送り、処理側で本人確認(固定値で代用)・権限(自分の依頼か)・状態(下書き・差戻しか)を確かめてから、08-02の保存処理で保存し、結果を返す—
前工程の成果物08-02の storage.js(コピーを同じフォルダに置く。関数名 createRequest・submitRequest・loadDb)保存処理の再実装(AIが保存処理を書き直すと08-02とのつながりが切れる。「呼ぶ」ことを指示する)
設計資料の該当部分05-03の権限表(依頼者は自分の依頼だけ提出できる)、05-02の「下書き→提出済み」「差戻し→提出済み」の行、04-04の失敗時の文言の方針承認・差戻しの連携(この記事の範囲外)
実行環境Node.js標準機能のみ(node:http・node:fs・node:path)、localhost のみ実際の認証の仕組み・実データ・外部サービス

指示文は次のとおりです。これは説明のために書いた例で、実際にAIへ送信した記録ではありません。

画面(クライアント)から「提出」操作を送り、処理側(サーバー)で確かめてから保存する一巡を、JavaScript(Node.js 標準機能のみ、localhost のみ)で実装してください。

渡す資料:
- storage.js(08-02 の保存処理のコピー。createRequest / submitRequest / loadDb を使うこと。保存処理を書き直さないこと)
- 05-03 権限表のうち「依頼者は自分の依頼だけ提出できる」の行
- 05-02 状態遷移表のうち「下書き → 提出済み」「差戻し → 提出済み」の行

完成条件:
- サーバーは POST /submit で { userId, requestId } を受け取る
- 1. 本人確認は固定値の対応表で代用する(実際の認証ではないとコードに書く)
- 2. 権限判定は、画面が送った内容ではなく、保存先から読み出した依頼の requester と userId を比べる
- 3. 状態の確認は、保存先から読み出した state が「下書き」「差戻し」のときだけ通す
- 4. 通ったら storage.js の submitRequest で保存し、200 と { result, state, historyCount } を返す
- 失敗は 401(本人確認)・403(権限)・409(状態)で、利用者向けの文言を返す。内部情報は返さない
- 画面側(client.js)は、正常・本人確認失敗・権限なし・状態不一致の4件を順に送り、状態コード・本文・待ち時間を表示する

返し方:
- server.js と client.js を返し、サーバーを起動して client.js を実行した stdout を、省略せずそのまま貼ってください。保存先(practice-db.json)の中身も貼ってください。

してはいけないこと:
- 承認・差戻しの処理を書かないでください。
- 本物の認証(パスワード、トークン)を実装しないでください。
- 待ち時間や時刻を固定値に書き換えないでください(実行のたびに変わる値として扱う)。

5.5 初稿のレビュー(説明用)

この記事の初版(Remediation Phase 1 より前)を「AIの初稿」という設定で扱い、何が不十分だったかを示します(実際のAI出力を観測したものではなく、初版の内容に基づく説明用の例です)。

問題点なぜ問題かどう見つけるか誰が判断するかどう直したか
「08-02の保存処理でつなぐ」と書きながら、サーバーが storage.js を呼んでいなかった前工程の成果物とのつながりが文章だけになる。08-02で直した内容が連携に反映されないserver.js の require に ./storage.js があるか、submitRequest が呼ばれているかを見る実装を確認する人(架空:開発担当)storage.js を08-02からコピーして置き、起動時の createRequest、判定の loadDb、保存の submitRequest を実際に呼ぶ形にした
掲載コードと examples/ の正本が一致せず、掲載出力が配布コードの実出力でなかった読者が正本を実行しても記事の出力にならない。「実行確認済み」が実測でない記事のコードブロックと正本を diff する。出力を正本で再実行して比べる開発担当正本を作り直し、記事のコードを正本と完全一致させ、出力を実測に置き換えた
権限判定に、画面が送った内容だけを使っていた「自分の依頼です」と申告した要求を止められない(第4節2行目)判定の条件式が input.〜 だけで書かれていないかを見る開発担当と、権限表の責任者保存先から依頼を読み出し、target.requester !== input.userId で判定する形にした
状態の確認が無かった提出済みの依頼をもう一度提出でき、05-02に無い遷移が通る状態遷移表の「提出できる状態」に対応する条件がコードにあるかを見る開発担当「下書き」「差戻し」のときだけ通す条件(手順3)を足し、409で返すようにした

見つけ方に共通するのは、「つなぐ」「確認する」と書いた文章に対応するコードの行を指せるか、を1つずつ問うことです。指せない文章は、実装されていないか、実装が文章と違います。

6. 実行結果(連携処理・実行記録)

examples/08-03-integration-log/ で、ターミナル1で node server.js、ターミナル2で node client.js を実行した stdout です(整形・省略なし。stderr への出力はありませんでした。waitMs は実測値で、実行のたびに変わります)。

画面側(node client.js):

$ node client.js
=== 1. 正常な提出(本人・自分の依頼・下書き) ===
{
  status: 200,
  body: { result: 'ok', state: '提出済み', historyCount: 2 },
  waitMs: 18
}
=== 2. 本人確認に失敗する場合(固定値と一致しないID) ===
{ status: 401, body: { error: '本人確認に失敗しました(固定値と一致しない)' }, waitMs: 1 }
=== 3. 権限がない場合(他人の依頼を提出しようとする) ===
{ status: 403, body: { error: '権限がありません(自分の依頼ではない)' }, waitMs: 1 }
=== 4. 状態が合わない場合(提出済みの依頼をもう一度提出する) ===
{ status: 409, body: { error: '状態が「提出済み」のため提出できません' }, waitMs: 0 }
終了コード: 0

処理側(node server.js。サーバーは Ctrl+C で止めるまで動き続けます):

$ node server.js
処理側サーバーが起動しました: http://localhost:8931
受け取った内容: { userId: 'u-sato', requestId: 'REQ-0001' }
受け取った内容: { userId: 'u-unknown', requestId: 'REQ-0001' }
受け取った内容: { userId: 'u-suzuki', requestId: 'REQ-0001' }
受け取った内容: { userId: 'u-sato', requestId: 'REQ-0001' }

応答のあとの保存先(practice-db.json)の中身です。状態が「提出済み」に変わり、履歴が「作成」「提出」の2件になっています(at の時刻は実行のたびに変わります)。

{
  "requests": [
    {
      "id": "REQ-0001",
      "requester": "u-sato",
      "title": "会議室の予約",
      "content": "9/25 10時から",
      "state": "提出済み",
      "approver": "u-suzuki"
    }
  ],
  "history": [
    {
      "requestId": "REQ-0001",
      "action": "作成",
      "actor": "u-sato",
      "at": "2026-09-20T10:56:53.432Z"
    },
    {
      "requestId": "REQ-0001",
      "action": "提出",
      "actor": "u-sato",
      "at": "2026-09-20T10:56:54.485Z"
    }
  ]
}

失敗時の動作(サーバーを止めてから node client-fail.js を実行):

$ node client-fail.js
通信失敗: ECONNREFUSED
終了コード: 0
連携の経路送る内容受け取る内容待ち時間失敗時の動作
画面→処理(POST /submit)→保存先(storage.js){ userId, requestId }{ result, state, historyCount } または { error }1件目 18ms、2件目以降 0〜1ms(実測、環境により変動する。1件目はサーバー側の保存処理を含む)通信自体が失敗した場合は ECONNREFUSED を画面側で受け取る(応答なし)

代用した箇所:本人確認は固定値の対応表(FIXED_USERS)による代用であり、実際の認証機能ではありません(設計書5.5)。

7. 確認結果

実行環境:macOS 26.6.2、Node.js v24.18.0(node:http・node:fs・node:path のみ使用)、2026-09-20に実行。教材演習用のローカル通信(localhost)と、このフォルダ内の practice-db.json だけを使い、外部のネットワーク・データベースには接続していません。stdout・stderr・終了コードをそのまま記録した実行記録は第9節の run_log.md にあります。

手順期待結果実際の結果一致
1. 正常な提出200、状態が提出済み、履歴が2件(作成+提出)status: 200、state: '提出済み'、historyCount: 2。保存先の practice-db.json も同じ内容一致
2. 本人確認の失敗401、保存先は変わらないstatus: 401一致
3. 権限なし403、保存先は変わらないstatus: 403一致
4. 提出済みをもう一度提出409、保存先は変わらない(履歴は2件のまま)status: 409、保存先の履歴は2件のまま一致
サーバー停止中の通信応答なし、ECONNREFUSED通信失敗: ECONNREFUSED一致

完了条件との照合:

完了条件確認結果
一巡の通信内容が記録されている第6節に画面側・処理側の両方の stdout と、保存先の中身を記載
処理側での権限判定の記録がある第6節「2.」「3.」「4.」に記載
代用(固定値の本人確認など)と未検証が明記されている第6節末尾、第11節に記載

残る制限:この通信は、ローカルの1台のパソコンの中だけで行ったものです。実際のネットワークを介した通信、外部サービスとの連携、複数の利用者からの同時の提出は、この記事の時点では確認していません。この記事の本文はClaude Codeが作成したもので、業務担当者による内容確認は行っていません。

8. 設計を判断する

8.1 許可判定を画面側だけでなく処理側で行う理由

04-02で説明したとおり、画面側の表示条件は誤操作を防ぐものであり、直接の操作を防ぐものではありません。この記事の実装では、処理側(サーバー)で本人確認・権限判定・状態の確認を行っており、画面を経由しない直接のリクエストに対しても、権限のない操作や状態に合わない操作を拒否できます(第6節「2.」「3.」「4.」の結果が示すとおり)。判定に使う依頼の情報は保存先から読み出しているので、画面側が送ってきた内容だけを信用していません。

8.2 連携の失敗時の扱いを比較する

選択肢内容適する場合
再試行通信が失敗した場合、一定回数まで自動的に再送する一時的な通信の乱れが原因と考えられる場合
中断失敗したらその場で操作を止め、利用者に伝える(この記事で採用)原因が分からない失敗、または繰り返し失敗する場合
通知失敗を記録し、運用担当に知らせる繰り返し失敗する場合、影響が大きい場合

この記事の教材演習では、失敗したらその場で中断し、利用者に伝える方法を採用しています。再試行や通知の仕組みは、08-04で扱うエラー処理の一部として検討します。

8.3 適用限界

この連携は、1台のパソコンの中でのローカル通信を前提にしています。実際のネットワークを介した通信では、待ち時間や失敗の頻度が変わる可能性があり、この記事では確認していません。

9. 持ち帰る成果物

成果物空欄版記入例
連携処理・実行記録ひな形(連携の経路、送る内容、受け取る内容、待ち時間、失敗時の動作、代用した箇所)templates/08-03-integration-log_template.mdtemplates/08-03-integration-log_example.md
処理側・画面側コード一式examples/08-03-integration-log/(server.js、client.js、client-fail.js、storage.js=08-02のコピー)同上
実行記録(stdout・stderr・終了コード、整形なし)—evidence_public/remediation1-2026-09-20/08-03/run_log.md

自分の業務に使うときの手順は次のとおりです。

  1. 前工程(保存処理、権限表)を用意する
  2. 処理側で本人確認・権限判定・状態の確認を行い、保存処理を呼ぶ実装を作る
  3. 画面側から操作を送り、通信内容と待ち時間を記録する
  4. 失敗時の動作を確認し、代用した箇所を明記する

10. 次工程への受渡し

次へ渡すもの:処理側・画面側のコード、連携処理・実行記録。

次工程での使われ方:08-04(エラー処理と保守しやすさを整える)では、この連携の失敗時の扱いを改善します。09-03(例外・権限・同時操作・負荷を確認する)では、この連携をより広い範囲で検証します。

前工程へ戻る条件:この連携が05-03の権限表と食い違う場合は、05-03に戻って確認します。

11. 根拠と更新情報

  • この記事の会社・人物・データはすべて架空の設定です。
  • 権限判定の条件は、05-03の権限表に基づきます。
  • 本人確認を固定値で代用する演習が実際の認証ではない点は、教材設計書AI_SYSTEM_DEV_BLUEPRINT_v0.1.md第5.5節に基づきます。
  • 制作の来歴:本文はClaude Codeが作成しました。第5〜7節のコードは examples/08-03-integration-log/ を正本とし、2026-09-20にmacOS 26.6.2・Node.js v24.18.0の環境で実際にローカル通信を実行して、stdout・stderr・終了コードを evidence_public/remediation1-2026-09-20/08-03/run_log.md に記録しています。人(ユーザー)による実読・内容確認は未実施です。
  • 2026-09-20(Remediation Phase 1):受入監査で「掲載コードと examples/ の正本が一致せず、掲載出力は配布コードの実出力ではない」「08-02の保存処理を使わずに『つないだ』と記述」と指摘された。処理側を08-02の storage.js を呼ぶ形に作り直し(状態の確認と保存先の中身の記録も追加)、本文のコードと実行結果をすべて正本の実測に置き換えた。
  • 第5.4節の指示文は、この記事のために書いた指示文の例であり、実際にAIへ送信した記録ではありません。第5.5節の初稿は、この記事の初版の内容を説明用に整理したものです。
  • 2026-09-20(Phase 5B-2B):読む順路(3つの深さ)、第4節の判断項目、第5.4節「AIに連携処理を頼む」(渡す情報と指示文、AI WORKFLOW)、第5.5節「初稿のレビュー」、CHECKLIST、記事間の参照を追加した。コード・実行結果・実行記録(Remediation Phase 1)は変えていない。
  • 未確認事項:実際のネットワークを介した通信、外部サービスとの連携、複数の利用者からの同時の提出は、この記事の時点では確認していません。