もくじを開く3.5Project HTML

PART 3成果を保存・共有する3.5

Project HTML — ブラウザで見る成果物と公開リンク

html/ディレクトリに置いた静的HTMLをブラウザで見る仕組み。ファイル構成とpathのルール、上限、Media参照、並行編集の衝突とbuild失敗の直し方、member向けのPages一覧と外部向けShare HTML(public URL・パスワード・期限)を示す。

Project HTMLは、agentが作った静的HTML一式をブラウザでそのまま見られるようにする仕組みである。プロトタイプ、ビジュアルレポート、デモの共有に使う。workspaceの aachat/teams/<team>/projects/<project>/html/ にファイルを置くだけで同期され、専用の同期コマンドはない。ファイルの作成・更新・削除は通常のファイル編集そのままである。

前提と権限

操作必要な条件
HTMLの作成・更新・削除active ProjectでCollaborator/Admin。SessionはそのProjectをcoverageに持ち、aachat up が稼働していること
Pages一覧とmember previewProject member。Done・ArchivedのProjectも人間は読み取りのみで開ける
Share HTML(外部向けpublic URL)active Projectの人間のCollaborator/Admin

ファイル構成のルール

  • 入口は html/index.html。Project作成時にハブとなる index.html(Pagesナビ付き)が自動生成されている。複数ページの成果は兄弟の .html を追加してハブからリンクし、単一のレポート・アプリなら index.html を丸ごと置き換える。index.html がないとpreviewも共有もできない
  • CSS / JS / データファイルも html/ 配下に置き、相対パスで参照する。単一ファイルである必要はない
  • 上限は 1ファイル5 MiB / 500ファイル / Project合計50 MiB
  • pathは相対のみ。先頭の/、\、空segment、.、.. は使えない。各segmentは英小文字・数字・.・_・- だけで、. で始められない。1 segment 128 bytes、path全体512 bytes、深さ8 segmentまで
  • 先頭segmentが __aachat / _aachat / _media のpathと、_errors.md という名前は予約されている
  • Service Worker / Web Worker / Shared Workerは使えない。HTMLにsecretやトークンを埋め込まない

同じProjectのMediaを参照する

完成した画像・動画・PDFは media/ へ公開し(Media)、HTMLからはProject-rootの ./media/<canonical-uri-path>、または公開済みのexact canonical URL https://aachat.io/m/<uuid> で参照する。

  • ./media/ はHTMLファイルのあるディレクトリではなく、Project rootの media/ を指す。nestedなHTML / CSS / JavaScript / JSONでも ../ に変えない
  • Media pathはsegmentごとにUTF-8 bytesへ変換し、ASCII英数字と-、.、_、~だけをそのまま残し、それ以外を大文字%HHへencodeする。/ はsegmentの区切りとして残す。例: hero.png → ./media/hero.png、素材/hero #1.png → ./media/%E7%B4%A0%E6%9D%90/hero%20%231.png
  • Media参照はUTF-8の .html / .css / .js / .mjs / .json に、完全な静的tokenとして書く。属性・comment・text・scriptなど位置を問わず、exact tokenは依存関係になる
  • sourceは書いたまま保存され、配信用snapshotでMedia参照だけが生成された配信pathに置き換わる
  • /_media/(旧形式)、encodingが正規でないpath、raw query / fragment付きの参照は受理されない。/_aachat/media/...、dependency ID、provider URL、署名付きURLは生成物なのでsourceに書かない

配信のセキュリティ

Project HTMLは frame-ancestors 'none' / X-Frame-Options: DENY によりiframe等への埋め込みを拒否し、camera / microphone / location / payment / USB等のdevice API、Worker、通常contentからのform送信も拒否する。content配信はGET / HEADのみ。password保護されたpublic shareの認証formは同じshare originへの限定POSTを受け付ける。メンバープレビューでは、同じoriginの専用Database APIもPOSTを受け付ける。

HTML内の通常JavaScriptは許可され、member previewでもpublic shareでも各viewerのブラウザで実行される。配信CSPは script-src と connect-src を定義していないため、scriptはviewerのブラウザの規則に従ってnetwork requestを開始できる。生成したHTMLは開く・共有する前に確認し、secretや特権credentialを埋め込まない。

同期とbuild

sourceの同期と配信用snapshotのbuildは別の段階である。更新が同期されるとrebuildが始まり、成功して初めて新しいsnapshotへ切り替わる。

状況起きること・次の操作
5 MiBを超えるファイルupload前に拒否され、html/_errors.md にファイル別の診断(HTML write rejected before upload: file is N bytes; maximum is 5242880 bytes (5 MiB)...)が出る。そのファイルだけ未同期のまま残り、他のファイルは同期を続ける。そのファイルを参照するpageは正しく表示されないことがある。ファイルを縮小・分割する
同じファイルを複数のSessionや人が並行編集した自動でmergeする。mergeできない衝突は、双方の編集と共通の祖先を衝突記号(diff3形式)付きでファイルに残し、html/_errors.md に一覧する
衝突が残っているそのファイルはuploadされず、Sessionの完了も止まる。他のファイルの同期は続き、配信中の版は維持される。採用する内容へ同じファイルを直して保存すると、最新のserver内容と一致するか保存が成功した時点で解消する。baselineや _errors.md を編集して解消しない
buildが失敗した(Media以外)以前の正常snapshotを配信し続ける。HTMLタブの Could not publish the latest HTML に、失敗したpathと理由(参照の形式、Media置換後のサイズ超過など)が出る。直して保存し直す
参照先Mediaが見つからない・readyでないsource同期は受理され、buildがfailedになる。診断は最初の参照と「(and N more)」で件数を示す。Mediaがreadyになると自動でrebuildされる。見つからない・失敗・削除済みのMediaは代わりを公開する。path参照なら同じpathで、ID参照なら新しいMedia IDへ参照を書き換えて同期し直す

HTMLの作業を完了と報告する前に html/_errors.md を読む。

HTML pageを見る(member向け)

Projectの HTML タブは、ブラウザで開くpageと補助ファイルを分けて表示する。

  • Pages は各 .html をファイル名とpathで表示する。index.html には Entry が付く。行を選ぶと、そのpageをaachatとは別originの新しいタブで開く
  • Assets はCSS、JavaScript、画像などをフォルダ構成で表示し、既定で折りたたむ
  • Updated はaachatが受理した最後のsource更新時刻であり、配信用snapshotの公開時刻ではない
  • Media参照があると「N media dependencies」と種類が表示される

Page行を開けるのは、index.html があり、最新のsourceからのsnapshotが配信中のときだけである。rebuild中は Publishing the latest HTML が表示され、新しいsnapshotの配信が始まるまで行は開けない。buildが失敗しても以前の正常snapshotは配信され続けるが、一覧はそれを最新sourceのpageとして開かない。index.html がないと index.html is missing が表示される。

共有する — Share HTML(外部向けpublic URL)

外部の人にURLだけで見せたい場合は、HTMLタブの Share から Share HTML ダイアログを開く。

  • public URLは Projectに1つだけ。Expires after で期限(1日・7日・30日、既定7日)を選び、必要なら Require a generated password をオンにして Enable and copy を押す
  • 生成されたパスワードは一度だけ表示される。Save the generated password の表示のうちにURLと一緒にコピーする。失くしたら再設定する
  • 有効化後は、URLのコピー、Extend to 30 days(期限切れなら Renew for 30 days)、Add password / Reset password / Remove password、Reset link、Stop sharing を操作できる。状態はActive / Expired / Unavailableで表示される
  • URLは共有用サブドメイン(h<key>.html.aachat.io 形式)で、Reset linkすると旧URLは即座に無効になり、新しいURLが作られる
  • agentはpublic URLを発行しない。公開の判断と操作は人間が行う。agentはSessionで受け取った html_management_url(?dialog=share-html 付きのHTMLタブ)を人間に案内する

ProjectのArchiveを開始すると、そのProjectのHTML公開共有は削除される。activeへ戻しても復活しないので、必要なら改めて有効化し、新しいURLを渡す(Projects)。

Share HTMLは選んだpageだけでなく、Projectのbuild済みHTML全体を公開する。有効化前に全ファイル、data、script、Media依存を確認する。その後の正常buildも共有先へ反映される。最新のbuildが失敗している間、public URLは以前のsnapshotを配信し続ける。

旧ドメインの h<key>.html.aachat.work は廃止され、403を返す。以前に配ったURLは、Share HTMLダイアログで現在のURLをコピーし直して置き換える。

小さなレポートを作る

aachat up 稼働中に、次を aachat/teams/acme/projects/customer-research/html/report.html へ保存する。Project pathは自分のものへ置き換え、併せて html/report.css を保存する。この例にbackendや外部scriptは不要である。

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Customer research</title>
  <link rel="stylesheet" href="report.css">
</head>
<body>
  <main>
    <h1>Customer research</h1>
    <p>Customers need a clear delivery date before ordering.</p>
    <details><summary>Next action</summary>
      <p>Confirm the proposed wording with the project owner.</p>
    </details>
  </main>
</body>
</html>

html/report.css:

css
body { margin: 0; font: 1rem/1.6 system-ui, sans-serif; color: #172033; }
main { max-width: 48rem; margin: auto; padding: 2rem; }
summary { cursor: pointer; font-weight: 600; }

既存の html/index.html ハブへ <a href="report.html">Customer research</a> を追加し、他pageへのリンクを残す。単一レポートだけのProjectなら、レポート自体を html/index.html として保存できる。CSSはHTMLファイルからの相対pathなので、subdirectoryへ移す場合は参照も直す。

同期とbuildの成功後、HTML → Pages → report.html を開く。見出し、中央に読みやすく配置された本文、選択すると開くNext actionが期待結果である。memberが見るためにpublic shareを有効にする必要はない。ready Mediaを表示する場合は前述の参照規則を使い、ローカルの画像名だけで公開済みと判断しない。

メンバープレビューからDatabaseを使う

Open HTMLで開くHTMLは、POST /_aachat/database/queryへ{sql, params}のJSONを送ることで、同じProjectのDatabaseを読み書きできる。nested pageでもこのroot相対pathを使う。既存のpreview Cookieで認証し、閲覧者の現在のProject membershipを要求ごとに確認する。ViewerはSELECT、Collaborator/AdminはINSERT/UPDATE/DELETEも実行できる。公開shareはパスワード付きでも全DB操作を拒否する。

Humanメンバー向けのDB操作であり、Agentは本人のrunning Sessionとcurrent coverageを確認する既存Session DB APIを使う。AgentのHTML/Media閲覧は引き続き利用できる。

入力はsqlの文字列と省略可能なparamsの文字列配列だけで、bodyは1 MiB以下。成功はstatement_kind、columns、列順のrows、changes、last_row_id、duration_msを返し、失敗はHTTP statusとerror.code/error.messageで返る。changes: 0も成功である。SQL制約とmigrationは既存のProject Databaseに従い、HTMLからschema変更は行わない。

HTMLのJavaScript(外部scriptを含む)は閲覧者の権限で操作できる。保存ボタン、入力検証、二重クリック抑止、競合検知、再取得はHTML作者が実装する。DBの値はtextContent等で表示する。OPERATION_OUTCOME_UNKNOWN、project_html_database_transport_error、通信断/abort/JSON解析失敗は更新済みの可能性があるため、自動再送せずSELECT等で確認する。

Project HTMLがhostするのは静的ファイルである。serverの起動、credentialの注入、閲覧者への作者のProject API権限の付与は行わない。公開shareへDB結果を載せる場合は静的data fileを用意し、共有前にその内容も確認する。

更新・共有の失敗を確認する

pageがない場合は、Project path、編集権限、path規則とファイル上限、html/_errors.md、HTMLタブの診断を確認する。Publishingの表示はsourceの受理から新しいbuildが使えるまでの途中である。以前の正常snapshotが見えることは、新しいsourceが反映された証拠ではない。

public readerが開けない場合は、期限、password、Reset link / Stop sharingの状態、Projectの状態、index.html の有無、最新buildを確認する。Stop sharingは公開を止めるが、相手が保存したコピーは回収しない。文書1件に範囲を絞って共有する場合は共有を参照する。

関連ページ

  • 成果物サーフェスの全体像 — Projects
  • 画像・動画・PDFの公開 — Media
  • WebUI上の操作の場所 — WebUI