コンテンツにスキップ

パース確定(アセンブルのキュー投入)

メソッド

このAPIはRESTメソッドを採用しています。

HTTPメソッド

POST: 対話型生成ランのパースチェックポイントを確定し、アセンブルフェーズをキューに投入します(または、拒否パスの場合はパースを却下します)。

このエンドポイントは対話型フロー(autoConfirm = false)にのみ適用されます。自動確定ランはパースからアセンブルへ単一のワーカー呼び出しで直接連鎖し、確定チェックポイントには到達しません。

命名規則

一貫性と可読性を確保するため、リクエストとレスポンス内のJSONノードにはcamelCaseを使用します。SQSペイロードのノードにはsnake_caseを使用します。

リクエストとレスポンス

ヘッダー

メタ情報はレスポンスボディではなく、HTTPヘッダーに設定されます。

リクエストヘッダー

  • Authorization
  • Content-Type
  • Accept
  • Accept-language

レスポンスヘッダー

  • Content-Type

パース確定

URI

POST /api/v1/organizations/{organization_id}/projects/{project_id}/wf2des/{wf2des_id}/confirm

パスパラメータ

Name Type Required Description
organization_id integer Required 組織ID
project_id integer Required プロジェクトID
wf2des_id string Required wf2des ID

リクエストボディ

リクエストボディはJSONです。

{
  "attempt": 1,
  "parseArtifactHash": "8f14e45fceea167a5a36dedd4bea2543"
}

リクエストパラメータ

Name Type Required Description
attempt integer Required プラグインがプレビューした試行回数。行のattemptに対してcompare-and-setを行う。不一致は、レビュー対象のパースがより新しいパースに置き換えられたことを意味する(409)。
parseArtifactHash string Required プラグインがプレビューしたparse.jsonアーティファクトのコンテンツハッシュ。キュー投入前に現在のパースアーティファクトと比較される。不一致は409。

レスポンス

レスポンスはJSONです(HTTPステータス: 200 OK)。

{
  "wf2desId": "wf2des-001",
  "status": "0",
  "phase": "2",
  "attempt": 1
}

レスポンスフィールド

Name Type Description
wf2desId string wf2des ID
status string 確定後の行ステータス。確定時は'0'処理中(アセンブルがキュー投入済み)。拒否時は'3'拒否済み。
phase string | null status '0'内の生成フェーズ。確定後は'2'アセンブル。拒否後はnull(クリア済み)。
attempt integer 確定された試行回数(エコー)。

このエンドポイントは冪等です。すでにphase '2'アセンブルへ進行済みのラン(同一attempt)に対する確定の繰り返しは、同一のボディで200を返し、何もキュー投入しません。アセンブルメッセージは最初の呼び出しですでに送信済みです。すでにstatus '3'にあるランに対する拒否の繰り返しも同様に、拒否形式のボディで200を返します。

パース拒否

拒否は同じチェックポイントの代替的な結果です。デザイナーがパースを確定する代わりに却下します。これは失敗ではありません。status '2'失敗とは区別される、終端のstatus '3'拒否済みです。

拒否は詳細を先に・フラグを後に(detail-first-flag-last)の2ステップシーケンスです。

  1. 詳細を先に。 プラグインは拒否詳細を内部wf2des-apiデータプレーンに書き込み、これがdesign_generation_resultドキュメントのparse.rejectedブロックへ永続化されます。
{
  "reasonCode": "wrong_roles",
  "note": "The hero CTA was tagged as a body label."
}
Name Type Required Description
reasonCode string (enum) Required wrong_roles、wrong_memos、wrong_sections、otherのいずれか。
note string Optional 自由記述の説明。reasonCode = otherの場合に推奨。
  1. フラグを後に。 このエンドポイント(拒否バリアントとして呼び出す。リクエストボディ{ "attempt": 1, "reject": true })は、同じ(attempt, phase awaiting_confirm)のcompare-and-setのもとで行をstatus '3'拒否済みに切り替えます。フラグを切り替える前に詳細を書き込むことで、status '3'の行が常にparse.rejectedブロックを持つことが保証されます。拒否パスではアセンブルメッセージはキュー投入されません。

拒否されたparse.rejected詳細は、後の再トリガーが消費するものです。新しいパース(attempt + 1)がキュー投入され、拒否理由がそれとともに伝わるため、ワーカーはパースキャッシュをスキップします(新しいパースを行うことが目的です)。

認証

認証はAmazon Cognitoが発行するJSON Web Token(JWT)を使用して行われます。

例外処理

エラーに対して以下のステータスコードが返却されます。

Description Status Code Status Name
リクエストボディの欠落または無効(確定時にattempt欠落/parseArtifactHash欠落、拒否時に未知のreasonCode) 400 Bad Request
認証情報の欠落 401 Unauthorized
権限不足 403 Forbidden
wf2des、プロジェクト、または組織が見つからない 404 Not Found
compare-and-setの不一致: attemptが一致しない、または行がphase '1' awaiting_confirmにない(アセンブル済み、終端、または自動確定) 409 Conflict
内部サーバーエラー 500 Internal Server Error

すでに適用済みの状態に一致する確定/拒否の繰り返し(同一attempt、対象のphase/statusがすでに設定済み)では、エンドポイントは409ではなく200(冪等エコー)を返します。409は、置き換えられたランまたは誤ったフェーズのランという、真のattempt/phase不一致のために予約されています。

処理フロー

確定パス

  1. パスパラメータから組織ID、プロジェクトID、wf2des_idを抽出し、リクエストボディからattemptとparseArtifactHashを抽出する。
  2. ユーザーがプロジェクトへのWriteアクセス権を持つことを確認する。
  3. wf2des行をロードする。存在しない場合(またはそのproject_idが一致しない場合)、404を返す。
  4. 冪等エコーチェック: 行がすでに同一attemptでphase '2'アセンブルにある場合、キュー投入せずに確定ボディで200を返す。
  5. compare-and-set: status = '0'処理中、phase = '1' awaiting_confirm、および行のattemptがリクエストのattemptと等しいことを要求する。不一致の場合、409を返す。
  6. parseArtifactHashを当該ランの現在のparse.jsonアーティファクトハッシュに対して検証する。不一致の場合、409を返す。
  7. 同じ(attempt, phase '1')条件でガードして、アトミックにphase = '2'アセンブルを設定する(行はstatus '0'のまま)。
  8. アセンブルメッセージをSQS生成キューへ送信する(snake_caseペイロード。下記参照)。
  9. 更新された行(status '0'、phase '2')を返す。

拒否パス

  1. パスパラメータと拒否ボディ(attempt、reject = true)を抽出する。
  2. ユーザーがプロジェクトへのWriteアクセス権を持つことを確認する。
  3. wf2des行をロードする。存在しないかプロジェクトが一致しない場合は404。
  4. 冪等エコーチェック: 行がすでにstatus '3'拒否済みにある場合、拒否ボディで200を返す。
  5. 拒否詳細がwf2des-api経由でdesign_generation_resultドキュメントのparse.rejectedブロックへすでに書き込まれていることを確認する(detail-first-flag-last)。欠落している場合、400を返す。
  6. compare-and-set: status = '0'、phase = '1' awaiting_confirm、およびattemptの一致を要求する。不一致の場合は409。
  7. アトミックにstatus = '3'拒否済みに切り替え、phaseをクリアする(NULL)。SQSメッセージは送信されない。
  8. 更新された行(status '3'、phase null)を返す。

詳細フローチャート

flowchart TD
    Start([POST /confirm]) --> Auth[Auth & Parameter Extraction]
    Auth --> Service[Service Layer]

    Service --> AccessCheck[Access Check]
    AccessCheck --> HasAccess{Write Access?}
    HasAccess -->|No| Err403[403 Forbidden]
    HasAccess -->|Yes| LoadRow[Load wf2des Row]

    LoadRow --> RowExists{Exists &<br/>project matches?}
    RowExists -->|No| Err404[404 Not Found]
    RowExists -->|Yes| Branch{Reject flag?}

    Branch -->|No confirm| EchoC{Already phase '2'<br/>assemble, same attempt?}
    EchoC -->|Yes| Ok200[200 OK<br/>idempotent echo]
    EchoC -->|No| CASConfirm{status '0' &<br/>phase '1' awaiting_confirm &<br/>attempt matches?}
    CASConfirm -->|No| Err409[409 Conflict]
    CASConfirm -->|Yes| HashCheck{parseArtifactHash<br/>matches parse.json?}
    HashCheck -->|No| Err409
    HashCheck -->|Yes| SetAssemble[CAS set phase '2' assemble<br/>row stays status '0']
    SetAssemble --> SendSQS[Send assemble message<br/>to SQS generation queue]
    SendSQS --> SQSResult{Success?}
    SQSResult -->|No| Err500[500 Internal Server Error]
    SQSResult -->|Yes| SuccessC[200 OK<br/>status '0' / phase '2']

    Branch -->|Yes reject| EchoR{Already status '3'<br/>rejected?}
    EchoR -->|Yes| Ok200
    EchoR -->|No| DetailCheck{parse.rejected detail<br/>written via wf2des-api?}
    DetailCheck -->|No| Err400[400 Bad Request]
    DetailCheck -->|Yes| CASReject{status '0' &<br/>phase '1' awaiting_confirm &<br/>attempt matches?}
    CASReject -->|No| Err409
    CASReject -->|Yes| SetRejected[CAS flip status '3' rejected<br/>clear phase NULL<br/>no SQS]
    SetRejected --> SuccessR[200 OK<br/>status '3' / phase null]

非同期処理

確定パスでは、アセンブルフェーズはSQSワーカー上で非同期に実行されます。ワーカーはdesign_generation_resultドキュメントのinputsブロックから入力ピンをリハイドレートし、終端のspec/selection/validator_report/confidenceブロックを書き込みます。ワーカーは決してPostgreSQLに書き込みません。完了はバックエンド側でai-status webhookハンドラーによって適用され、行を切り替えます。

  • status '0'(処理中)/phase '2'(アセンブル)→ status '1'(完了、phaseクリア)またはstatus '2'(失敗、phaseクリア)

拒否パスはこのエンドポイントで終端です。ワーカーは実行されず、webhookも発火しません。

SQSペイロード

確定パスでSQS生成キューへ送信されるアセンブルメッセージです。アセンブルワーカーが必要とするその他すべてはdesign_generation_resultドキュメントのinputsブロックからリハイドレートされます。メッセージはランのアイデンティティ、フェンシングペア、確定判断のみを運びます。

{
  "wf2des_id": "wf2des-001",
  "attempt": 1,
  "nonce": "b1946ac92492d2347c6235b4d2611184",
  "confirm": {
    "attempt": 1,
    "parse_artifact_hash": "8f14e45fceea167a5a36dedd4bea2543"
  }
}

SQSペイロードフィールド

Name Type Required Description
wf2des_id string Required wf2des ID(= PG行ID。完了webhookではjob_idとしてエコーされる)。
attempt integer Required フェンシングカウンター。DocumentDBの結果ドキュメント書き込みをフェンスする((_id, attempt)のCAS)。
nonce string Required キュー投入ごとに新規生成。(job_id, attempt, nonce) webhook重複排除キーの一部。
confirm.attempt integer Required 確定された試行回数(このエンドポイントがキュー投入前にCASで一致させた値)。
confirm.parse_artifact_hash string Required 確定されたparse.jsonアーティファクトハッシュ(このエンドポイントがキュー投入前に検証した値)。

拒否パスではSQSメッセージは送信されません。