From 305343adf363cc39b9eebdfe55f3b4132a0031e8 Mon Sep 17 00:00:00 2001 From: hitalin Date: Tue, 13 Oct 2026 20:47:32 +0900 Subject: [PATCH] =?UTF-8?q?fix(contract):=20endpoint=20=E5=AF=BE=E5=BF=9C?= =?UTF-8?q?=E8=A1=A8=E3=81=AE=E5=BC=95=E7=94=A8=E7=AC=A6=E3=81=AA=E3=81=97?= =?UTF-8?q?=E3=81=AE=E3=82=AD=E3=83=BC=E3=82=82=E8=AA=AD=E3=82=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit notedeck の MISSKEY_ENDPOINT_RULES は biome が識別子として書けるキー (meta / i / emojis / stats …) の引用符を外している。同期スクリプトは 引用符つきのキーしか読まず 14 件を落としていたため、それらを呼ぶ配布物が 「表に無い endpoint」と誤判定されていた (notedeck#1250)。 - 引用符なしのキーも読み、読めない行があれば黙って落とさず失敗する - 同じ notedeck のコミット (25a2567f) からスナップショットを取り直す - known-gaps の 4 件は誤検知だったので消す Co-Authored-By: Claude Opus 5.5 --- docs/design/contract-check.md | 5 +++-- scripts/contract/known-gaps.json | 7 +------ scripts/contract/notedeck-contract.json | 16 +++++++++++++++- scripts/sync-notedeck-contract.mjs | 10 ++++++++-- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/docs/design/contract-check.md b/docs/design/contract-check.md index 9b76e06..51db507 100644 --- a/docs/design/contract-check.md +++ b/docs/design/contract-check.md @@ -167,5 +167,6 @@ issue が閉じたら該当行を消す。消し忘れは次のスナップシ 「降格対象なのに違反が出ない」状態になるだけで安全側だが、`contract-drift` の issue 本文に known-gaps の件数を出すので気づける。 -初期エントリ: `meta` / `i` / `emojis` / `stats`(notedeck#1250。14 件の配布物が NoteDeck 上で -該当呼び出しに到達すると止まる)。 +初期エントリだった `meta` / `i` / `emojis` / `stats`(notedeck#1250)は notedeck 側の欠落ではなく、 +同期スクリプトが引用符つきのキーしか読んでいなかったための誤検知だった(biome は識別子として +書けるキーの引用符を外す)。同期スクリプトは引用符なしのキーも読み、読めない行があれば失敗する。 diff --git a/scripts/contract/known-gaps.json b/scripts/contract/known-gaps.json index 7b2da77..1286582 100644 --- a/scripts/contract/known-gaps.json +++ b/scripts/contract/known-gaps.json @@ -1,9 +1,4 @@ { "$comment": "notedeck 側の既知の欠落。ここに挙げた違反は verify-contract が warning に降格する。issue が閉じたら該当行を消すこと (消し忘れは contract-drift が拾う)。", - "endpoints": { - "meta": { "issue": "https://github.com/notedeck-dev/notedeck/issues/1250", "note": "misskeyEndpoints.generated.ts に無い (本家は公開 endpoint)。14 件の配布物が NoteDeck で止まる" }, - "i": { "issue": "https://github.com/notedeck-dev/notedeck/issues/1250", "note": "同上。本家は read:account" }, - "emojis": { "issue": "https://github.com/notedeck-dev/notedeck/issues/1250", "note": "同上。本家は公開 endpoint" }, - "stats": { "issue": "https://github.com/notedeck-dev/notedeck/issues/1250", "note": "同上。本家は公開 endpoint" } - } + "endpoints": {} } diff --git a/scripts/contract/notedeck-contract.json b/scripts/contract/notedeck-contract.json index 57d1321..17d2354 100644 --- a/scripts/contract/notedeck-contract.json +++ b/scripts/contract/notedeck-contract.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-10-12T10:42:54.123Z", + "generatedAt": "2026-10-13T11:45:02.243Z", "source": { "repo": "notedeck-dev/notedeck", "ref": "25a2567f07744eeea648468412614b61f7831205", @@ -1788,6 +1788,7 @@ "admin/update-meta": "deny:admin", "admin/update-proxy-account": "deny:admin", "admin/update-user-note": "deny:admin", + "announcements": "allow", "announcements/show": "allow", "antennas/create": "account.write", "antennas/delete": "account.write", @@ -1873,6 +1874,7 @@ "clips/show": "account.read", "clips/unfavorite": "clips.write", "clips/update": "account.write", + "drive": "drive.read", "drive/files": "drive.read", "drive/files/attached-chat-messages": "drive.read", "drive/files/attached-notes": "drive.read", @@ -1893,6 +1895,10 @@ "drive/folders/update": "drive.write", "drive/stream": "drive.read", "email-address/available": "allow", + "emoji": "allow", + "emojis": "allow", + "endpoint": "allow", + "endpoints": "allow", "export-custom-emojis": "deny:credential-required-without-kind", "federation/followers": "allow", "federation/following": "allow", @@ -1940,6 +1946,7 @@ "hashtags/show": "allow", "hashtags/trend": "allow", "hashtags/users": "allow", + "i": "account.read", "i/2fa/done": "deny:credential-required-without-kind", "i/2fa/key-done": "deny:credential-required-without-kind", "i/2fa/password-less": "deny:credential-required-without-kind", @@ -2000,11 +2007,13 @@ "invite/delete": "deny:no-mapped-key(write:invite-codes)", "invite/limit": "account.read", "invite/list": "account.read", + "meta": "allow", "miauth/gen-token": "deny:credential-required-without-kind", "mute/create": "account.write", "mute/delete": "account.write", "mute/list": "account.read", "my/apps": "account.read", + "notes": "allow", "notes/children": "allow", "notes/clips": "allow", "notes/conversation": "allow", @@ -2052,6 +2061,7 @@ "pages/show": "allow", "pages/unlike": "deny:no-mapped-key(write:page-likes)", "pages/update": "deny:no-mapped-key(write:pages)", + "ping": "allow", "pinned-users": "allow", "promo/read": "account.write", "renote-mute/create": "account.write", @@ -2060,6 +2070,7 @@ "request-reset-password": "allow", "reset-db": "allow", "reset-password": "allow", + "retention": "allow", "reversi/cancel-match": "account.write", "reversi/games": "allow", "reversi/invitations": "account.read", @@ -2072,11 +2083,14 @@ "roles/show": "allow", "roles/users": "allow", "server-info": "allow", + "stats": "allow", "sw/register": "deny:credential-required-without-kind", "sw/show-registration": "deny:credential-required-without-kind", "sw/unregister": "allow", "sw/update-registration": "deny:credential-required-without-kind", + "test": "allow", "username/available": "allow", + "users": "allow", "users/achievements": "allow", "users/clips": "allow", "users/featured-notes": "allow", diff --git a/scripts/sync-notedeck-contract.mjs b/scripts/sync-notedeck-contract.mjs index f1760c6..a05e9ce 100644 --- a/scripts/sync-notedeck-contract.mjs +++ b/scripts/sync-notedeck-contract.mjs @@ -143,8 +143,14 @@ function parseEndpoints(text) { if (start < 0) throw new Error('misskeyEndpoints.generated.ts に MISSKEY_ENDPOINT_RULES が無い') const body = text.slice(text.indexOf('{', start), text.indexOf('\n}', start)) const endpoints = {} - for (const m of body.matchAll(/^\s*'([^']+)':\s*'([^']+)',?\s*$/gm)) { - endpoints[m[1]] = m[2] + // biome は識別子として書けるキー (meta / i / emojis …) の引用符を外す (notedeck#1250) + const entry = /^\s*(?:'([^']+)'|([A-Za-z_$][\w$]*)):\s*'([^']+)',?\s*$/ + for (const line of body.split('\n').slice(1)) { + if (!line.trim()) continue + const m = line.match(entry) + // 読めない行を黙って落とすと「表に無い」と誤判定するので止める + if (!m) throw new Error(`MISSKEY_ENDPOINT_RULES の行を読めない: ${line.trim()}`) + endpoints[m[1] ?? m[2]] = m[3] } return sortObject(endpoints) }