@qijenchen/design-system 0.1.0-beta.108 → 0.1.0-beta.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AccountMenu/account-menu.d.ts.map +1 -1
- package/dist/components/AccountMenu/account-menu.js +2 -1
- package/dist/components/AccountMenu/account-menu.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js +1 -1
- package/ds-canonical/adapters/claude-settings-base.json +1 -1
- package/ds-canonical/fork/AGENTS.md +1 -1
- package/ds-canonical/fork/codex/agents/skills/independent-review/references/evidence-contract.md +8 -9
- package/ds-canonical/fork/codex/hooks.json +1 -1
- package/ds-canonical/fork/common/closed-tool-execution.mjs +5 -1
- package/ds-canonical/fork/common/instruction.md +1 -1
- package/ds-canonical/fork/consumer/governance-check.mjs +1 -1
- package/ds-canonical/fork/consumer/lib/closed-tool-execution.mjs +5 -1
- package/ds-canonical/fork/consumer/lock.json +18 -18
- package/ds-canonical/fork/consumer/managed-files/2d1ef5617a5ce3c39ad9aae1c42af7d199f9270c0a0ccb490b63d62dbc6913db.blob +5 -1
- package/ds-canonical/fork/consumer/managed-files/46f10bc55cdfdf834d0749eebff42ea0bb8576f361b36d2b6ba1851354c50150.blob +65 -16
- package/ds-canonical/fork/consumer/managed-files/63061e05969667005020166ea2ae7df3c96663f7a928e7dd3eebc1471022df56.blob +1 -1
- package/ds-canonical/fork/consumer/managed-files/7eb6cc60abfdabaf6617c336058fad1454ccde08889295767bfd9b7fd153cc6e.blob +3 -3
- package/ds-canonical/fork/governance.lock +21 -21
- package/ds-canonical/fork/hooks/check_pattern_invariants.sh +5 -0
- package/ds-canonical/fork/launchers/approval-evidence.mjs +38 -2
- package/ds-canonical/fork/launchers/provider-hook-output-transport.mjs +15 -0
- package/ds-canonical/fork/launchers/settings-hooks.json +2 -2
- package/ds-canonical/fork/manifest.json +11 -10
- package/ds-canonical/fork/providers/claude/hook-config.json +1 -1
- package/ds-canonical/fork/providers/claude/skills/independent-review/references/evidence-contract.md +8 -9
- package/ds-canonical/fork/providers/codex/hook-config.json +1 -1
- package/ds-canonical/fork/providers/codex/skills/independent-review/references/evidence-contract.md +8 -9
- package/ds-canonical/fork/skills/independent-review/references/evidence-contract.md +8 -9
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +62 -2
- package/ds-canonical/hooks/check_benchmark_citation.sh +5 -0
- package/ds-canonical/hooks/check_main_branch_workbench.sh +1 -1
- package/ds-canonical/hooks/check_pattern_invariants.sh +5 -0
- package/ds-canonical/hooks/check_propose_discipline.sh +25 -4
- package/ds-canonical/hooks/check_solo_workflow.sh +1 -1
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +2 -2
- package/ds-canonical/hooks/lib/_hardcoded_strings.sh +5 -0
- package/ds-canonical/hooks/lib/approval-evidence.mjs +38 -2
- package/ds-canonical/hooks/session_start_governance_check.sh +7 -4
- package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +4 -2
- package/ds-canonical/references/certified-surfaces.md +5 -10
- package/ds-canonical/references/repository-hygiene-policy.json +1 -1
- package/ds-canonical/references/repository-hygiene.md +10 -0
- package/ds-canonical/rules/meta-patterns.md +1 -1
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +4 -2
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +11 -3
- package/ds-canonical/skills/independent-review/references/evidence-contract.md +8 -9
- package/ds-canonical/skills/new-component/SKILL.md +1 -1
- package/ds-canonical/templates/product-provider-wiring.json +1 -0
- package/ds-canonical/templates/product-provider-wiring.schema.json +3 -2
- package/package.json +1 -1
- package/src/components/AccountMenu/account-menu.anatomy.stories.tsx +3 -1
- package/src/components/AccountMenu/account-menu.tsx +6 -2
- package/src/components/Tag/tag.spec.md +1 -1
- package/ds-canonical/hooks/tests/KNOWN-BROKEN.md +0 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../../src/components/AccountMenu/account-menu.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,0CAA0C,CAAA;AAYlF,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,KAAK,CAAC,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAClE;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc;IACd,IAAI,EAAE,eAAe,CAAA;IACrB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,yCAAyC;IACzC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC;;;;OAIG;IACH,YAAY,CAAC,EAAE,IAAI,CACjB,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC,EACxC,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,UAAU,CAC9D,CAAA;CACF;AAID,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../../src/components/AccountMenu/account-menu.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,0CAA0C,CAAA;AAYlF,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,KAAK,CAAC,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAClE;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc;IACd,IAAI,EAAE,eAAe,CAAA;IACrB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,yCAAyC;IACzC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC;;;;OAIG;IACH,YAAY,CAAC,EAAE,IAAI,CACjB,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC,EACxC,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,UAAU,CAC9D,CAAA;CACF;AAID,eAAO,MAAM,WAAW,4FAiFvB,CAAA;AAKD,eAAO,MAAM,eAAe;;;;;;;;;;;CAWlB,CAAA"}
|
|
@@ -12,6 +12,7 @@ const AccountMenu = React.forwardRef(
|
|
|
12
12
|
children,
|
|
13
13
|
align = "end",
|
|
14
14
|
triggerAriaLabel = "帳號與設定",
|
|
15
|
+
// i18n-allow: spec 預設 aria-label(account-menu.spec.md),consumer 以同名 prop 覆蓋
|
|
15
16
|
open,
|
|
16
17
|
defaultOpen,
|
|
17
18
|
onOpenChange,
|
|
@@ -31,7 +32,7 @@ const AccountMenu = React.forwardRef(
|
|
|
31
32
|
ref,
|
|
32
33
|
type: "button",
|
|
33
34
|
"aria-label": triggerAriaLabel,
|
|
34
|
-
className: "flex items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
35
|
+
className: "flex size-6 shrink-0 items-center justify-center self-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
35
36
|
children: /* @__PURE__ */ jsx(Avatar, { size: 24, ...avatar, alt: avatar.alt ?? user.name })
|
|
36
37
|
}
|
|
37
38
|
) }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-menu.js","sources":["../../../src/components/AccountMenu/account-menu.tsx"],"sourcesContent":["/**\n * AccountMenu — 全域 chrome「自己的帳號入口」(24px avatar 觸發 + 帳號選單)\n *\n * ── 定位 ──\n * Primary-header 派 globalHeader 右側(desktop)/ mobile Sheet SidebarHeader 右側的\n * 帳號入口成品元件:點 avatar 開「個人資料 / 設定 / 登出」navigation 選單。\n * 是「自己」的入口,不是看「別人」的 ProfileCard(後者預設動作 Chat/通話,語義是聯絡某人)。\n * **Placement-agnostic**:哪個 mode 放哪裡是 consumer 職責,放置 canonical owner =\n * `../AppShell/app-shell.spec.md`「帳號入口(Account entry)放置 SSOT」(本元件不收 mode prop,\n * 不複製該 SSOT;consumer 讀 `useAppShell().layout` + `useSidebar().isMobile` 決定放置)。\n *\n * ── 實作基礎 ──\n * 消費:Avatar(raw size=24 trigger)+ DropdownMenu(Trigger asChild / Content / Group / Label / Item)\n * 對應 pattern:patterns/header-canonical(4.5 chrome header avatar SSOT)\n *\n * ── 消費的 SSOT ──\n * - components: [Avatar, DropdownMenu(DropdownMenuTrigger/Content/Group/Label/Item)]\n * - patterns: [header-canonical 4.5(chrome header avatar = raw `<Avatar size={24}>`,非 ItemAvatar)]\n * - tokens: [--chrome-header-avatar-size(JS 端 24 literal sync), --ring(focus-visible ring canonical)]\n * - spec refs: app-shell.spec.md「帳號入口(Account entry)放置 SSOT」/ header-canonical.spec.md 4.5\n * / dropdown-menu.spec.md / profile-card.spec.md(近親分界:看別人 vs 自己)\n *\n * 升級歷程:2026-06-17 `AppShell/_demo-helpers.tsx` demo helper 誕生(user directive)→\n * 2026-07-30 F9 升 public:app-shell.spec.md + sidebar.spec.md 兩處 canonical 都 mandate\n * 消費本元件,「文件教得到、import 拿不到」= DT-EXPORT 斷鏈同款缺口(gen-component-indexes.mjs\n * 檔頭 anchor),npm consumer 被迫整包重造。世界級對照:Atlassian `@atlaskit/atlassian-navigation`\n * 出貨專門 `Profile` 元件作 top bar 帳號 trigger(ProfileProps = IconButtonProps,選單內容\n * composition;https://unpkg.com/@atlaskit/atlassian-navigation/dist/types/index.d.ts +\n * dist/types/components/Profile/types.d.ts);shadcn / Primer 走 DropdownMenu / ActionMenu\n * composition recipe(https://ui.shadcn.com/docs/components/dropdown-menu「An account switcher\n * dropdown triggered by an avatar」/ https://primer.style/components/action-menu)。本元件 =\n * Atlassian 專門元件 + shadcn canonical 內容組(Label(user)+ Groups)的收斂。\n */\nimport * as React from 'react'\nimport { User, Settings, LogOut } from 'lucide-react'\nimport { Avatar, type AvatarData } from '@/design-system/components/Avatar/avatar'\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuGroup,\n} from '@/design-system/components/DropdownMenu/dropdown-menu'\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface AccountMenuUser {\n /** 顯示名(選單 Label 區;alt 未傳時同時作 avatar alt fallback) */\n name: string\n /**\n * Avatar 資料(消費既有 `AvatarData` type)。`hoverCard` 刻意排除:帳號入口是「自己」,\n * 不掛 ProfileCard(per app-shell.spec.md 帳號入口 SSOT「不用 ProfileCard」);\n * `alt` 可省,fallback `name`。\n */\n avatar?: Omit<AvatarData, 'hoverCard' | 'alt'> & { alt?: string }\n}\n\nexport interface AccountMenuProps {\n /** 當前登入使用者 */\n user: AccountMenuUser\n /** 「個人資料」item handler(default 選單消費;命名對齊 `PersonData.onViewProfile` 既有 canonical) */\n onViewProfile?: () => void\n /** 「設定」item handler(default 選單消費) */\n onOpenSettings?: () => void\n /** 「登出」item handler(default 選單消費) */\n onSignOut?: () => void\n /**\n * 取代 default 選單內容(自組 `DropdownMenuGroup` / `DropdownMenuItem`;i18n / 產品自訂項走這)。\n * Identity Label(user.name)恆由本元件渲染於選單頂(對齊 shadcn account 例 Label(user)慣例);\n * 傳入 children 時三個 default callback 不再消費。\n */\n children?: React.ReactNode\n /** 選單對齊(轉傳 DropdownMenuContent `align`)。預設 `'end'`:右上入口靠右展開(demo baseline) */\n align?: 'start' | 'center' | 'end'\n /** Trigger aria-label(i18n override,對齊 Avatar `badgeAriaLabel` pattern)。預設「帳號與設定」 */\n triggerAriaLabel?: string\n /** 受控展開狀態(Radix passthrough) */\n open?: boolean\n /** 預設展開(uncontrolled,Radix passthrough)。Storybook OpenSnapshot(M15 visual-audit coverable)用 */\n defaultOpen?: boolean\n /** 展開狀態變更 callback(Radix passthrough) */\n onOpenChange?: (open: boolean) => void\n /**\n * Trigger button 的非視覺 DOM attributes / event handlers。\n * `children`、`type`、`aria-label`、`className`、`disabled` 由 AccountMenu canonical contract\n * 擁有;分析與測試所需的 `data-*`、`aria-*`、事件可由此傳入。\n */\n triggerProps?: Omit<\n React.ComponentPropsWithoutRef<'button'>,\n 'children' | 'type' | 'aria-label' | 'className' | 'disabled'\n >\n}\n\n// ── AccountMenu ─────────────────────────────────────────────────────────────\n\nexport const AccountMenu = React.forwardRef<HTMLButtonElement, AccountMenuProps>(\n ({\n user,\n onViewProfile,\n onOpenSettings,\n onSignOut,\n children,\n align = 'end',\n triggerAriaLabel = '帳號與設定'
|
|
1
|
+
{"version":3,"file":"account-menu.js","sources":["../../../src/components/AccountMenu/account-menu.tsx"],"sourcesContent":["/**\n * AccountMenu — 全域 chrome「自己的帳號入口」(24px avatar 觸發 + 帳號選單)\n *\n * ── 定位 ──\n * Primary-header 派 globalHeader 右側(desktop)/ mobile Sheet SidebarHeader 右側的\n * 帳號入口成品元件:點 avatar 開「個人資料 / 設定 / 登出」navigation 選單。\n * 是「自己」的入口,不是看「別人」的 ProfileCard(後者預設動作 Chat/通話,語義是聯絡某人)。\n * **Placement-agnostic**:哪個 mode 放哪裡是 consumer 職責,放置 canonical owner =\n * `../AppShell/app-shell.spec.md`「帳號入口(Account entry)放置 SSOT」(本元件不收 mode prop,\n * 不複製該 SSOT;consumer 讀 `useAppShell().layout` + `useSidebar().isMobile` 決定放置)。\n *\n * ── 實作基礎 ──\n * 消費:Avatar(raw size=24 trigger)+ DropdownMenu(Trigger asChild / Content / Group / Label / Item)\n * 對應 pattern:patterns/header-canonical(4.5 chrome header avatar SSOT)\n *\n * ── 消費的 SSOT ──\n * - components: [Avatar, DropdownMenu(DropdownMenuTrigger/Content/Group/Label/Item)]\n * - patterns: [header-canonical 4.5(chrome header avatar = raw `<Avatar size={24}>`,非 ItemAvatar)]\n * - tokens: [--chrome-header-avatar-size(JS 端 24 literal sync), --ring(focus-visible ring canonical)]\n * - spec refs: app-shell.spec.md「帳號入口(Account entry)放置 SSOT」/ header-canonical.spec.md 4.5\n * / dropdown-menu.spec.md / profile-card.spec.md(近親分界:看別人 vs 自己)\n *\n * 升級歷程:2026-06-17 `AppShell/_demo-helpers.tsx` demo helper 誕生(user directive)→\n * 2026-07-30 F9 升 public:app-shell.spec.md + sidebar.spec.md 兩處 canonical 都 mandate\n * 消費本元件,「文件教得到、import 拿不到」= DT-EXPORT 斷鏈同款缺口(gen-component-indexes.mjs\n * 檔頭 anchor),npm consumer 被迫整包重造。世界級對照:Atlassian `@atlaskit/atlassian-navigation`\n * 出貨專門 `Profile` 元件作 top bar 帳號 trigger(ProfileProps = IconButtonProps,選單內容\n * composition;https://unpkg.com/@atlaskit/atlassian-navigation/dist/types/index.d.ts +\n * dist/types/components/Profile/types.d.ts);shadcn / Primer 走 DropdownMenu / ActionMenu\n * composition recipe(https://ui.shadcn.com/docs/components/dropdown-menu「An account switcher\n * dropdown triggered by an avatar」/ https://primer.style/components/action-menu)。本元件 =\n * Atlassian 專門元件 + shadcn canonical 內容組(Label(user)+ Groups)的收斂。\n */\nimport * as React from 'react'\nimport { User, Settings, LogOut } from 'lucide-react'\nimport { Avatar, type AvatarData } from '@/design-system/components/Avatar/avatar'\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuGroup,\n} from '@/design-system/components/DropdownMenu/dropdown-menu'\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface AccountMenuUser {\n /** 顯示名(選單 Label 區;alt 未傳時同時作 avatar alt fallback) */\n name: string\n /**\n * Avatar 資料(消費既有 `AvatarData` type)。`hoverCard` 刻意排除:帳號入口是「自己」,\n * 不掛 ProfileCard(per app-shell.spec.md 帳號入口 SSOT「不用 ProfileCard」);\n * `alt` 可省,fallback `name`。\n */\n avatar?: Omit<AvatarData, 'hoverCard' | 'alt'> & { alt?: string }\n}\n\nexport interface AccountMenuProps {\n /** 當前登入使用者 */\n user: AccountMenuUser\n /** 「個人資料」item handler(default 選單消費;命名對齊 `PersonData.onViewProfile` 既有 canonical) */\n onViewProfile?: () => void\n /** 「設定」item handler(default 選單消費) */\n onOpenSettings?: () => void\n /** 「登出」item handler(default 選單消費) */\n onSignOut?: () => void\n /**\n * 取代 default 選單內容(自組 `DropdownMenuGroup` / `DropdownMenuItem`;i18n / 產品自訂項走這)。\n * Identity Label(user.name)恆由本元件渲染於選單頂(對齊 shadcn account 例 Label(user)慣例);\n * 傳入 children 時三個 default callback 不再消費。\n */\n children?: React.ReactNode\n /** 選單對齊(轉傳 DropdownMenuContent `align`)。預設 `'end'`:右上入口靠右展開(demo baseline) */\n align?: 'start' | 'center' | 'end'\n /** Trigger aria-label(i18n override,對齊 Avatar `badgeAriaLabel` pattern)。預設「帳號與設定」 */\n triggerAriaLabel?: string\n /** 受控展開狀態(Radix passthrough) */\n open?: boolean\n /** 預設展開(uncontrolled,Radix passthrough)。Storybook OpenSnapshot(M15 visual-audit coverable)用 */\n defaultOpen?: boolean\n /** 展開狀態變更 callback(Radix passthrough) */\n onOpenChange?: (open: boolean) => void\n /**\n * Trigger button 的非視覺 DOM attributes / event handlers。\n * `children`、`type`、`aria-label`、`className`、`disabled` 由 AccountMenu canonical contract\n * 擁有;分析與測試所需的 `data-*`、`aria-*`、事件可由此傳入。\n */\n triggerProps?: Omit<\n React.ComponentPropsWithoutRef<'button'>,\n 'children' | 'type' | 'aria-label' | 'className' | 'disabled'\n >\n}\n\n// ── AccountMenu ─────────────────────────────────────────────────────────────\n\nexport const AccountMenu = React.forwardRef<HTMLButtonElement, AccountMenuProps>(\n ({\n user,\n onViewProfile,\n onOpenSettings,\n onSignOut,\n children,\n align = 'end',\n triggerAriaLabel = '帳號與設定', // i18n-allow: spec 預設 aria-label(account-menu.spec.md),consumer 以同名 prop 覆蓋\n open,\n defaultOpen,\n onOpenChange,\n triggerProps,\n }, ref) => {\n // Dev-mode warning(對齊 ProfileCardDefaultActions dev-warn 先例):default 選單項沒接任何\n // handler = item 點了永遠沒反應;production 必接 callback 或自組 children。\n if (\n process.env.NODE_ENV !== 'production' &&\n !children &&\n !onViewProfile &&\n !onOpenSettings &&\n !onSignOut\n ) {\n // eslint-disable-next-line no-console\n console.warn(\n '[DS AccountMenu] default 選單項未接 onViewProfile/onOpenSettings/onSignOut——item 點擊無反應。請傳入 callback 或自組 children。'\n )\n }\n const avatar = user.avatar ?? {}\n return (\n <DropdownMenu open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n <DropdownMenuTrigger asChild>\n {/* 互動感由 focus-visible ring 提供(無 hover bg,chrome 輕量 entry),不放大到 field height\n — per app-shell.spec.md「Avatar 尺寸 + 邊距」+ header-canonical.spec.md 4.5 */}\n {/* size-6 = Avatar 24 的幾何鎖:trigger 是 Radix 的 anchor box,沒鎖尺寸時 flex 預設\n align-items: stretch 會把按鈕撐高(實測 min-h-32 容器 → 96px anchor → 選單視覺間距\n 44px,遠離 elevation.spec.md 的 8px canonical)。鎖死後 anchor ≡ avatar,任何容器\n 都維持 sideOffset=8 的視覺意圖;shrink-0 防壓縮對偶。user 2026-08-04 拍板。 */}\n <button\n {...triggerProps}\n ref={ref}\n type=\"button\"\n aria-label={triggerAriaLabel}\n className=\"flex size-6 shrink-0 items-center justify-center self-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\"\n >\n {/* 24 per header-canonical.spec.md 4.5 chrome header avatar canonical(brand + account 同尺寸); sync with --chrome-header-avatar-size */}\n <Avatar size={24} {...avatar} alt={avatar.alt ?? user.name} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align}>\n {children ? (\n <>\n <DropdownMenuGroup>\n <DropdownMenuLabel>{user.name}</DropdownMenuLabel>\n </DropdownMenuGroup>\n {children}\n </>\n ) : (\n <>\n {/* Default 選單集合 = app-shell.spec.md「入口開什麼」canonical(個人資料 / 設定 / 登出,\n 登出獨立 group — 破壞性動作分區,對齊 GitHub / Gmail / Slack 帳號選單慣例) */}\n <DropdownMenuGroup>\n <DropdownMenuLabel>{user.name}</DropdownMenuLabel>\n <DropdownMenuItem startIcon={User} onSelect={onViewProfile}>\n 個人資料\n </DropdownMenuItem>\n <DropdownMenuItem startIcon={Settings} onSelect={onOpenSettings}>\n 設定\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuGroup>\n <DropdownMenuItem startIcon={LogOut} onSelect={onSignOut}>\n 登出\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n },\n)\nAccountMenu.displayName = 'AccountMenu'\n\n// Story auto-compile metadata — F9 public 升級(2026-07-30)\n// Phase 2 fill needed: purpose descriptions + when rationale\nexport const accountMenuMeta = {\n component: 'AccountMenu',\n family: null, // composite(trigger = chrome header 24px avatar;浮層 = DropdownMenu Family 1 消費者)\n variants: {},\n sizes: {}, // trigger avatar 24px density-fixed(header-canonical.spec.md 4.5),無 size 軸 → 兩欄留空為 intentional\n states: ['default', 'focus-visible'],\n tokens: {\n bg: [],\n fg: [],\n ring: ['--ring'], // trigger focus-visible ring canonical\n },\n} as const\n"],"names":[],"mappings":";;;;;AAgGO,MAAM,cAAc,MAAM;AAAA,EAC/B,CAAC;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,mBAAmB;AAAA;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GACC,QAAQ;AAGT,QACE,QAAQ,IAAI,aAAa,gBACzB,CAAC,YACD,CAAC,iBACD,CAAC,kBACD,CAAC,WACD;AAEA,cAAQ;AAAA,QACN;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM,SAAS,KAAK,UAAU,CAAA;AAC9B,WACE,qBAAC,cAAA,EAAa,MAAY,aAA0B,cAClD,UAAA;AAAA,MAAA,oBAAC,qBAAA,EAAoB,SAAO,MAO1B,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACE,GAAG;AAAA,UACJ;AAAA,UACA,MAAK;AAAA,UACL,cAAY;AAAA,UACZ,WAAU;AAAA,UAGV,UAAA,oBAAC,QAAA,EAAO,MAAM,IAAK,GAAG,QAAQ,KAAK,OAAO,OAAO,KAAK,KAAA,CAAM;AAAA,QAAA;AAAA,MAAA,GAEhE;AAAA,MACA,oBAAC,qBAAA,EAAoB,OAClB,UAAA,WACC,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,oBAAC,mBAAA,EACC,UAAA,oBAAC,mBAAA,EAAmB,UAAA,KAAK,MAAK,GAChC;AAAA,QACC;AAAA,MAAA,EAAA,CACH,IAEA,qBAAA,UAAA,EAGE,UAAA;AAAA,QAAA,qBAAC,mBAAA,EACC,UAAA;AAAA,UAAA,oBAAC,mBAAA,EAAmB,eAAK,KAAA,CAAK;AAAA,8BAC7B,kBAAA,EAAiB,WAAW,MAAM,UAAU,eAAe,UAAA,QAE5D;AAAA,8BACC,kBAAA,EAAiB,WAAW,UAAU,UAAU,gBAAgB,UAAA,KAAA,CAEjE;AAAA,QAAA,GACF;AAAA,QACA,oBAAC,qBACC,UAAA,oBAAC,kBAAA,EAAiB,WAAW,QAAQ,UAAU,WAAW,UAAA,KAAA,CAE1D,EAAA,CACF;AAAA,MAAA,EAAA,CACF,EAAA,CAEJ;AAAA,IAAA,GACF;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;AAInB,MAAM,kBAAkB;AAAA,EAC7B,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA,EACR,UAAU,CAAA;AAAA,EACV,OAAO,CAAA;AAAA;AAAA,EACP,QAAQ,CAAC,WAAW,eAAe;AAAA,EACnC,QAAQ;AAAA,IACN,IAAI,CAAA;AAAA,IACJ,IAAI,CAAA;AAAA,IACJ,MAAM,CAAC,QAAQ;AAAA;AAAA,EAAA;AAEnB;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { cva } from "class-variance-authority";
|
|
4
|
-
import {
|
|
4
|
+
import { lineClampClass, cn } from "../../lib/utils.js";
|
|
5
5
|
import { Avatar } from "../../components/Avatar/avatar.js";
|
|
6
6
|
import { Tooltip, TooltipTrigger, TooltipContent } from "../../components/Tooltip/tooltip.js";
|
|
7
7
|
import { useTruncated } from "../../hooks/use-truncated.js";
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
- Never install a mutable tag or semver range for internal packages. Upgrades are reviewed pull
|
|
23
23
|
requests that pin an exact version and include the regenerated lock/adapters.
|
|
24
24
|
<!-- canonical-decision-authority:start -->
|
|
25
|
-
**Decision/Engineering Authority**:user 只拍板產品/UI/UX SSOT 真取捨及可感知/產品語意變更(behavior/interaction/IA/visual/token/layout/content/a11y/canonical rules
|
|
25
|
+
**Decision/Engineering Authority**:user 只拍板產品/UI/UX SSOT 真取捨及可感知/產品語意變更(behavior/interaction/IA/visual/token/layout/content/a11y/canonical rules);核准 = user 在對話中對 exact target + choice 說可(**「我說可以就是可以,就是授權」— user 2026-08-04 verbatim**;最新一則 user 訊息的明確 blanket 授權即核准當下 pending 的 exact 提案)。operation digest 為可選佐證——有引且相符可加強、有引但不符 fail-closed、未引不阻擋(強制引 digest 屬已拆除的 per-PR 簽章同族儀式,835b519e 先例)。引用/條件/舊 scope/跨 target 無效。其餘工程/external writes 皆 Standing Authorization AUTO,含已核准 UI/UX 實作/機械 generation/sync 與 source→commit/PR/merge→canonical `infra/governance/release-workflow.json` 的 `pr-checks → merge → publish → readback → consumer`;依 frozen scope、SSOT、required checks、security、least privilege、rollback/readback 收斂,不逐 milestone 重問。Deep Audit 必須在單一 branch/PR 完成 remediation 與 local/CI candidate validation,禁止把 immutable publish 當 iteration/test loop,每次 audit 最多一次 final release;只有另有 evidence ref 綁定 incident ID、failure class、published version 的 post-publish blocker 或 security incident 才可額外 release。Certification、rollout、staged rollout、preview/canary 與 independent review 是明確要求時的附加 assurance,不得進入標準 five-step release blocking graph;peer 不可用只阻擋明確要求的 independent-review claim。
|
|
26
26
|
|
|
27
27
|
**Visual baseline**:user 對 exact image set/UI/UX 語意說「可以改」即拍板;Agent 自動 apply/generate/test/commit/PR/CI/merge,禁再核准/key enrollment/簽章。僅 user 明確要求 independent cryptographic review 才啟用 `visual-baseline-review-policy.json`,否則不阻擋。
|
|
28
28
|
|
package/ds-canonical/fork/codex/agents/skills/independent-review/references/evidence-contract.md
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
# Independent-review evidence contract
|
|
2
2
|
|
|
3
|
-
Use the transport
|
|
3
|
+
Use the transport selected by the generated provider binding. Do not invent a provider command, copy credentials into the repository, or create a second evidence schema.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The model-broker execution layer (evidence broker, shard/transcript carriers, model runner, managed-CI executors) was retired 2026-08-04; broker or managed receipts are permanently rejected. The surviving authority-owned contract surfaces are `scripts/lib/deep-audit-evidence-contract.mjs` (waived self-review and entitlement review-lane validation) and `scripts/lib/model-api-transport.mjs` (pure invocation-profile and response-substitution contract). A product reviewer consumes their validated receipt but never edits, publishes, or executes authority release controls. If a validated receipt is unavailable, use `LOCAL-REVIEW-ONLY` or `REVIEW-BLOCKED`, never managed or certified evidence.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
can upgrade a structural reduction to managed or promotion-eligible evidence.
|
|
7
|
+
A caller-supplied JavaScript callback, a self-declared model string, or structurally valid result
|
|
8
|
+
JSON is not transport attestation and can never yield `REVIEW-VALIDATED`. An independent-review
|
|
9
|
+
claim requires the entitlement review lane: a resolved provider binding whose peer, profile, and
|
|
10
|
+
entitlement readback are certified for the exact target, with response substitution fail-closed.
|
|
11
|
+
Without that binding the only honest outcomes are the waived self-review route (recorded waiver,
|
|
12
|
+
self-attested coverage, `unverifiedModelCoverage` visible) or `REVIEW-BLOCKED`.
|
|
14
13
|
|
|
15
14
|
Emit one closed review record in the response with:
|
|
16
15
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "_generated: build-fork-governance.mjs; provider=codex; sourceDigest=
|
|
2
|
+
"description": "_generated: build-fork-governance.mjs; provider=codex; sourceDigest=2cc48406238101fac213dcef260be8e289bf829275230cc8b77ccc08104935d1; exact npm corpus; native hooks are feedback only, provider-neutral check + protected CI are authoritative.",
|
|
3
3
|
"hooks": {
|
|
4
4
|
"SessionStart": [
|
|
5
5
|
{
|
|
@@ -66,12 +66,14 @@ const CLOSED_HOOK_EXECUTABLE_CANDIDATES = Object.freeze({
|
|
|
66
66
|
bash: Object.freeze(['/bin/bash']),
|
|
67
67
|
git: Object.freeze(['/usr/bin/git']),
|
|
68
68
|
jq: Object.freeze(['/usr/bin/jq']),
|
|
69
|
+
perl: Object.freeze(['/usr/bin/perl']),
|
|
69
70
|
python3: Object.freeze(['/usr/bin/python3']),
|
|
70
71
|
}),
|
|
71
72
|
linux: Object.freeze({
|
|
72
73
|
bash: Object.freeze(['/usr/bin/bash', '/bin/bash']),
|
|
73
74
|
git: Object.freeze(['/usr/bin/git']),
|
|
74
75
|
jq: Object.freeze(['/usr/bin/jq']),
|
|
76
|
+
perl: Object.freeze(['/usr/bin/perl']),
|
|
75
77
|
python3: Object.freeze(['/usr/bin/python3']),
|
|
76
78
|
}),
|
|
77
79
|
})
|
|
@@ -717,7 +719,9 @@ export function materializeClosedHookToolProfile({
|
|
|
717
719
|
)
|
|
718
720
|
const canonicalRepo = canonicalRepositoryRoot(repoRoot)
|
|
719
721
|
const executableRecords = Object.fromEntries(
|
|
720
|
-
|
|
722
|
+
// perl added 2026-08-04: three canonical hooks and the hardcoded-strings lib shell out to it,
|
|
723
|
+
// so the pinned tool profile has to declare it like every other hook interpreter.
|
|
724
|
+
['bash', 'git', 'jq', 'node', 'perl', 'python3'].map((label) => [
|
|
721
725
|
label,
|
|
722
726
|
resolveClosedHookExecutable({
|
|
723
727
|
label,
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
- Never install a mutable tag or semver range for internal packages. Upgrades are reviewed pull
|
|
23
23
|
requests that pin an exact version and include the regenerated lock/adapters.
|
|
24
24
|
<!-- canonical-decision-authority:start -->
|
|
25
|
-
**Decision/Engineering Authority**:user 只拍板產品/UI/UX SSOT 真取捨及可感知/產品語意變更(behavior/interaction/IA/visual/token/layout/content/a11y/canonical rules
|
|
25
|
+
**Decision/Engineering Authority**:user 只拍板產品/UI/UX SSOT 真取捨及可感知/產品語意變更(behavior/interaction/IA/visual/token/layout/content/a11y/canonical rules);核准 = user 在對話中對 exact target + choice 說可(**「我說可以就是可以,就是授權」— user 2026-08-04 verbatim**;最新一則 user 訊息的明確 blanket 授權即核准當下 pending 的 exact 提案)。operation digest 為可選佐證——有引且相符可加強、有引但不符 fail-closed、未引不阻擋(強制引 digest 屬已拆除的 per-PR 簽章同族儀式,835b519e 先例)。引用/條件/舊 scope/跨 target 無效。其餘工程/external writes 皆 Standing Authorization AUTO,含已核准 UI/UX 實作/機械 generation/sync 與 source→commit/PR/merge→canonical `infra/governance/release-workflow.json` 的 `pr-checks → merge → publish → readback → consumer`;依 frozen scope、SSOT、required checks、security、least privilege、rollback/readback 收斂,不逐 milestone 重問。Deep Audit 必須在單一 branch/PR 完成 remediation 與 local/CI candidate validation,禁止把 immutable publish 當 iteration/test loop,每次 audit 最多一次 final release;只有另有 evidence ref 綁定 incident ID、failure class、published version 的 post-publish blocker 或 security incident 才可額外 release。Certification、rollout、staged rollout、preview/canary 與 independent review 是明確要求時的附加 assurance,不得進入標準 five-step release blocking graph;peer 不可用只阻擋明確要求的 independent-review claim。
|
|
26
26
|
|
|
27
27
|
**Visual baseline**:user 對 exact image set/UI/UX 語意說「可以改」即拍板;Agent 自動 apply/generate/test/commit/PR/CI/merge,禁再核准/key enrollment/簽章。僅 user 明確要求 independent cryptographic review 才啟用 `visual-baseline-review-policy.json`,否則不阻擋。
|
|
28
28
|
|
|
@@ -1254,7 +1254,7 @@ const executionRuntimeValid = Boolean(
|
|
|
1254
1254
|
&& executionRuntime.nativeWindowsPolicy === 'unsupported-fail-closed'
|
|
1255
1255
|
&& JSON.stringify(executionRuntime.supportedHostPlatforms) === JSON.stringify(['darwin', 'linux'])
|
|
1256
1256
|
&& JSON.stringify(executionRuntime.windowsCompatibilityEnvironments) === JSON.stringify(['devcontainer-linux', 'wsl2-linux'])
|
|
1257
|
-
&& JSON.stringify(executionRuntime.requiredExecutables) === JSON.stringify(['bash', 'git', 'jq', 'node', 'python3'])
|
|
1257
|
+
&& JSON.stringify(executionRuntime.requiredExecutables) === JSON.stringify(['bash', 'git', 'jq', 'node', 'perl', 'python3'])
|
|
1258
1258
|
&& JSON.stringify(executionRuntime.requiredPathClasses) === JSON.stringify(['plain', 'space-containing'])
|
|
1259
1259
|
)
|
|
1260
1260
|
if (!executionRuntimeValid) add('GOV-RUNTIME-001', 'BLOCKER', 'installed consumer execution runtime contract is missing, open-shaped, or unsupported')
|
|
@@ -66,12 +66,14 @@ const CLOSED_HOOK_EXECUTABLE_CANDIDATES = Object.freeze({
|
|
|
66
66
|
bash: Object.freeze(['/bin/bash']),
|
|
67
67
|
git: Object.freeze(['/usr/bin/git']),
|
|
68
68
|
jq: Object.freeze(['/usr/bin/jq']),
|
|
69
|
+
perl: Object.freeze(['/usr/bin/perl']),
|
|
69
70
|
python3: Object.freeze(['/usr/bin/python3']),
|
|
70
71
|
}),
|
|
71
72
|
linux: Object.freeze({
|
|
72
73
|
bash: Object.freeze(['/usr/bin/bash', '/bin/bash']),
|
|
73
74
|
git: Object.freeze(['/usr/bin/git']),
|
|
74
75
|
jq: Object.freeze(['/usr/bin/jq']),
|
|
76
|
+
perl: Object.freeze(['/usr/bin/perl']),
|
|
75
77
|
python3: Object.freeze(['/usr/bin/python3']),
|
|
76
78
|
}),
|
|
77
79
|
})
|
|
@@ -717,7 +719,9 @@ export function materializeClosedHookToolProfile({
|
|
|
717
719
|
)
|
|
718
720
|
const canonicalRepo = canonicalRepositoryRoot(repoRoot)
|
|
719
721
|
const executableRecords = Object.fromEntries(
|
|
720
|
-
|
|
722
|
+
// perl added 2026-08-04: three canonical hooks and the hardcoded-strings lib shell out to it,
|
|
723
|
+
// so the pinned tool profile has to declare it like every other hook interpreter.
|
|
724
|
+
['bash', 'git', 'jq', 'node', 'perl', 'python3'].map((label) => [
|
|
721
725
|
label,
|
|
722
726
|
resolveClosedHookExecutable({
|
|
723
727
|
label,
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"schemaVersion": 1,
|
|
4
4
|
"role": "template-consumer",
|
|
5
5
|
"release": {
|
|
6
|
-
"designSystem": "0.1.0-beta.
|
|
7
|
-
"storybookConfig": "0.1.0-beta.
|
|
6
|
+
"designSystem": "0.1.0-beta.110",
|
|
7
|
+
"storybookConfig": "0.1.0-beta.110"
|
|
8
8
|
},
|
|
9
9
|
"upgradeTrust": {
|
|
10
10
|
"schemaVersion": 1,
|
|
@@ -42,24 +42,24 @@
|
|
|
42
42
|
"implementationSha256": "98b74118fb5b410b77ad2994aa9105fa7609c7353822f8c5213cce54d94f0af4"
|
|
43
43
|
},
|
|
44
44
|
"payload": {
|
|
45
|
-
"forkCorpusLockSha256": "
|
|
45
|
+
"forkCorpusLockSha256": "aedc7698f22b0762f672bcc7abd005e7ae3e7fa5b74ea659317743504597a634",
|
|
46
46
|
"discoveryPolicySha256": "fba289aeeb5a3f11139b9589f7ab08b5e8c8799c7bdf8f0ea57ebfeb8e7c9da6",
|
|
47
47
|
"providerMaterializersSha256": "732e85b01a12e7dd19469e26e4427f0e0cfe5117a78fc9f69c2f0f89702f463a",
|
|
48
|
-
"providerLifecycleSha256": "
|
|
48
|
+
"providerLifecycleSha256": "12d735f89b49b79afdb9580d8dc5e79296aa7d3ca27db9f0639805492c8b94b6",
|
|
49
49
|
"providerInventorySha256": "00adf1c4f6b3367055a9cc3fdfe658660771b4c9931f696e12761a95076ad92c",
|
|
50
|
-
"executionRuntimeSha256": "
|
|
51
|
-
"commonInstructionSha256": "
|
|
50
|
+
"executionRuntimeSha256": "d9377cc45308731f287d7b1711b7c38fc4e02ff8f84729bcbbf01bb52d136904",
|
|
51
|
+
"commonInstructionSha256": "6b9aa8747d9ddc9bd9a78de88a0c3d65f5b100ea917c4dd69be4d889b8299438",
|
|
52
52
|
"providerArtifactDigests": {
|
|
53
53
|
"claude": {
|
|
54
54
|
"instructionSha256": "f56a44c730506258cc7e2581dbdd31bfd1e6d13d60dc8a8ee8bcc398228453fb",
|
|
55
|
-
"hookSha256": "
|
|
56
|
-
"skillsSha256": "
|
|
55
|
+
"hookSha256": "5c197ea686f697ea84d88a591f762dfd0ecbbf84f24a942c7d4f7d2e15f6acff",
|
|
56
|
+
"skillsSha256": "20482e66e435d0d05669e1a10836f08e42c88f88261f9eba6236fd0a0b78e052",
|
|
57
57
|
"treeDigests": {}
|
|
58
58
|
},
|
|
59
59
|
"codex": {
|
|
60
|
-
"instructionSha256": "
|
|
61
|
-
"hookSha256": "
|
|
62
|
-
"skillsSha256": "
|
|
60
|
+
"instructionSha256": "6b9aa8747d9ddc9bd9a78de88a0c3d65f5b100ea917c4dd69be4d889b8299438",
|
|
61
|
+
"hookSha256": "de8b8a9739dc9736cfe28004cbbc462dae525485202c871af9265d4dd8049740",
|
|
62
|
+
"skillsSha256": "6411ba088fd09f048caca23083e5ef5367887632dd3c604b11f6a1cab5060466",
|
|
63
63
|
"treeDigests": {}
|
|
64
64
|
},
|
|
65
65
|
"generic": {
|
|
@@ -70,11 +70,11 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"mergeSurfaceDigests": {
|
|
73
|
-
"claude": "
|
|
73
|
+
"claude": "5c197ea686f697ea84d88a591f762dfd0ecbbf84f24a942c7d4f7d2e15f6acff"
|
|
74
74
|
},
|
|
75
|
-
"governanceCheckSha256": "
|
|
75
|
+
"governanceCheckSha256": "1c4c4455910f1e88aebb84add9f756717395519d84913beafaa654a9f1c3126e",
|
|
76
76
|
"utilityRegistrySha256": "ac430d50ee82c19eb678f725c00eec23a0e25b33ec4bad81d3bf6e2fa9fa64ff",
|
|
77
|
-
"sharedSkillsSha256": "
|
|
77
|
+
"sharedSkillsSha256": "4b74fb7b317ea53c7819f8e439f92bf5a45369840fd38892ad203b1fd11cdfd0",
|
|
78
78
|
"sharedSkillCount": 11,
|
|
79
79
|
"requiredScripts": {
|
|
80
80
|
"audit:a11y": "node scripts/audit-consumer-a11y.mjs",
|
|
@@ -106,17 +106,17 @@
|
|
|
106
106
|
"scripts/consumer-source-harness.mjs": "725072155d0b15b373bf6befb333cd2085dc8a38fff8538b4f4c8ea56f9c5308",
|
|
107
107
|
"scripts/lib/a11y-static-server.mjs": "3ae8ca74a66ca5f155d1a1d0c97280d41f07556274c8c077705a489ebe6a7018",
|
|
108
108
|
"scripts/lib/canonical-path-containment.mjs": "0244e31dc3be5015bed3efd65a5a77086a2e4676e9ac79cd0801c8cde6a74fcd",
|
|
109
|
-
"scripts/lib/closed-tool-execution.mjs": "
|
|
109
|
+
"scripts/lib/closed-tool-execution.mjs": "eacd0cd92c5bff03e40ff4e82c02fae9bf2e6f543f157eef3d41c3ed8b7d3cb6",
|
|
110
110
|
"scripts/lib/consumer-control-plane-policy.mjs": "ea8b11ddc5c964ea742ccba5e6a3bc2f215db5d165afe2cca96192812287750c",
|
|
111
111
|
"scripts/lib/exact-workspace-dependencies.mjs": "3c9453e5228d7eaf1bfef3350585746e1aff1475411cb7cf8696bf9acdb048cf",
|
|
112
|
-
"scripts/lib/governance-dependency-bootstrap.mjs": "
|
|
112
|
+
"scripts/lib/governance-dependency-bootstrap.mjs": "79b84cd0a7a8f262d1445503528e1251bb510517efb56550aad659c53c6b3cec",
|
|
113
113
|
"scripts/lib/provider-lifecycle.mjs": "9aabb2c98efc454b8555308a34830e6590b034b10a63f76f788fbd4cf37ce7e7",
|
|
114
|
-
"scripts/lib/verified-exact-npm-runtime.mjs": "
|
|
114
|
+
"scripts/lib/verified-exact-npm-runtime.mjs": "811ed3390a4ff6b4e818a5ce8b5c0ce34e10f48fb443b6177d6e4c8e14fa9670",
|
|
115
115
|
"scripts/lib/workspace-post-create.mjs": "f3ddc6db740d5c4d48b1c6e16c55222325e4d1c16fe6644a455e7b7e5bea0a0d",
|
|
116
116
|
"scripts/lib/worktree-fingerprint.mjs": "70a8bdbceade964d009f6a46c9e57a93bc9fd58c28971ea14ad1b5ffeaaf7250",
|
|
117
117
|
"scripts/lint-ds-internal-imports.mjs": "86edd952fb5c3871896515440693abeb08c1d1da9f887fa073b9ddda1363f572",
|
|
118
118
|
"scripts/product-template-scaffold-lock.mjs": "9134dabf11af7a2445a6a026fc23201e8aba3ef5aeb7da1d2159e92956dd32d2",
|
|
119
|
-
"scripts/refresh-fork-launchers.mjs": "
|
|
119
|
+
"scripts/refresh-fork-launchers.mjs": "8d2058e9b32307a80e3a564f18abac6ea093d09e79164f468af5e1893217283f",
|
|
120
120
|
"scripts/release-bom-contract.mjs": "75d736f86c7f695dc88a1982d547998d510e8050c4847abe387227b6662b87c2",
|
|
121
121
|
"scripts/schemas/product-template-scaffold-lock.schema.json": "1318af59f12546b3cda059a1d94923d9a969bef4c5a476ebb46e42f8c853d19a",
|
|
122
122
|
"scripts/schemas/release-bom.schema.json": "6969482588a25533dc1896be63c3c9629aced1cbeb745b99822db764682dc4a4",
|
|
@@ -66,12 +66,14 @@ const CLOSED_HOOK_EXECUTABLE_CANDIDATES = Object.freeze({
|
|
|
66
66
|
bash: Object.freeze(['/bin/bash']),
|
|
67
67
|
git: Object.freeze(['/usr/bin/git']),
|
|
68
68
|
jq: Object.freeze(['/usr/bin/jq']),
|
|
69
|
+
perl: Object.freeze(['/usr/bin/perl']),
|
|
69
70
|
python3: Object.freeze(['/usr/bin/python3']),
|
|
70
71
|
}),
|
|
71
72
|
linux: Object.freeze({
|
|
72
73
|
bash: Object.freeze(['/usr/bin/bash', '/bin/bash']),
|
|
73
74
|
git: Object.freeze(['/usr/bin/git']),
|
|
74
75
|
jq: Object.freeze(['/usr/bin/jq']),
|
|
76
|
+
perl: Object.freeze(['/usr/bin/perl']),
|
|
75
77
|
python3: Object.freeze(['/usr/bin/python3']),
|
|
76
78
|
}),
|
|
77
79
|
})
|
|
@@ -717,7 +719,9 @@ export function materializeClosedHookToolProfile({
|
|
|
717
719
|
)
|
|
718
720
|
const canonicalRepo = canonicalRepositoryRoot(repoRoot)
|
|
719
721
|
const executableRecords = Object.fromEntries(
|
|
720
|
-
|
|
722
|
+
// perl added 2026-08-04: three canonical hooks and the hardcoded-strings lib shell out to it,
|
|
723
|
+
// so the pinned tool profile has to declare it like every other hook interpreter.
|
|
724
|
+
['bash', 'git', 'jq', 'node', 'perl', 'python3'].map((label) => [
|
|
721
725
|
label,
|
|
722
726
|
resolveClosedHookExecutable({
|
|
723
727
|
label,
|
|
@@ -233,24 +233,39 @@ function exactArray(value, expected) {
|
|
|
233
233
|
&& value.every((entry, index) => entry === expected[index])
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
// Exactly the advisory set the registry serves today for the copy bundled inside npm 11.19.0.
|
|
237
|
+
// The disk copy is replaced with the fixed 5.0.9 by the security overlay; npm audit reads the
|
|
238
|
+
// LOCK, which still records the bundled 5.0.7, so the finding itself never disappears — it is
|
|
239
|
+
// acknowledged here in exact shape and any drift (a third advisory, a new node) fails closed.
|
|
240
|
+
// 2026-08-04: GHSA-rgw5-rvv9-x895 landed (<5.0.9); overlay bumped 5.0.8 → 5.0.9 the same day.
|
|
236
241
|
const VERIFIED_BRACE_EXPANSION_AUDIT_PREIMAGES = Object.freeze([
|
|
237
242
|
Object.freeze({
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
source: 1130591,
|
|
244
|
-
findingRange: '4.0.0 - 5.0.7',
|
|
245
|
-
advisoryRange: '>=4.0.0 <5.0.8',
|
|
243
|
+
findingRange: '4.0.0 - 5.0.8',
|
|
244
|
+
advisories: Object.freeze([
|
|
245
|
+
Object.freeze({ source: 1130591, range: '>=4.0.0 <5.0.8', url: 'https://github.com/advisories/GHSA-mh99-v99m-4gvg', severity: 'high' }),
|
|
246
|
+
Object.freeze({ source: 1130734, range: '>=4.0.0 <5.0.9', url: 'https://github.com/advisories/GHSA-rgw5-rvv9-x895', severity: 'high' }),
|
|
247
|
+
]),
|
|
246
248
|
}),
|
|
247
249
|
])
|
|
248
250
|
|
|
251
|
+
function matchesExactAdvisorySet(finding, name, advisories) {
|
|
252
|
+
return Array.isArray(finding.via)
|
|
253
|
+
&& finding.via.length === advisories.length
|
|
254
|
+
&& advisories.every((advisory, index) => {
|
|
255
|
+
const via = finding.via[index]
|
|
256
|
+
return via?.source === advisory.source
|
|
257
|
+
&& via?.name === name
|
|
258
|
+
&& via?.dependency === name
|
|
259
|
+
&& via?.range === advisory.range
|
|
260
|
+
&& via?.url === advisory.url
|
|
261
|
+
&& via?.severity === advisory.severity
|
|
262
|
+
})
|
|
263
|
+
}
|
|
264
|
+
|
|
249
265
|
function matchesVerifiedBraceExpansionAuditPreimage(finding) {
|
|
250
266
|
return VERIFIED_BRACE_EXPANSION_AUDIT_PREIMAGES.some((preimage) => (
|
|
251
267
|
finding.range === preimage.findingRange
|
|
252
|
-
&& finding
|
|
253
|
-
&& finding.via[0]?.range === preimage.advisoryRange
|
|
268
|
+
&& matchesExactAdvisorySet(finding, 'brace-expansion', preimage.advisories)
|
|
254
269
|
))
|
|
255
270
|
}
|
|
256
271
|
|
|
@@ -265,17 +280,51 @@ function assertRemediatedFinding(name, finding) {
|
|
|
265
280
|
&& Array.isArray(finding.effects)
|
|
266
281
|
&& finding.effects.length <= 1
|
|
267
282
|
&& finding.effects.every((effect) => effect === 'minimatch')
|
|
268
|
-
&& Array.isArray(finding.via)
|
|
269
|
-
&& finding.via.length === 1
|
|
270
|
-
&& finding.via[0]?.name === 'brace-expansion'
|
|
271
|
-
&& finding.via[0]?.dependency === 'brace-expansion'
|
|
272
|
-
&& finding.via[0]?.url === 'https://github.com/advisories/GHSA-mh99-v99m-4gvg'
|
|
273
|
-
&& finding.via[0]?.severity === 'high'
|
|
274
283
|
&& matchesVerifiedBraceExpansionAuditPreimage(finding),
|
|
275
284
|
'npm audit brace-expansion finding differs from the exact remediated bundled preimage',
|
|
276
285
|
)
|
|
277
286
|
return
|
|
278
287
|
}
|
|
288
|
+
if (name === 'ip-address') {
|
|
289
|
+
// Bundled inside npm 11.19.0 and NOT yet overlaid — unlike brace-expansion/tar, the disk copy
|
|
290
|
+
// is still the vulnerable version. Acknowledged in exact shape only because no 11.x npm ships a
|
|
291
|
+
// fix and the overlay machinery has no third slot yet; the fixed 10.4.0 exists, and extending
|
|
292
|
+
// the overlay (or moving to npm 12) is tracked in the cloud-compat baton as the next branch.
|
|
293
|
+
// DoS-class parsing advisories in dev-only npm CLI internals; nothing ships to production from
|
|
294
|
+
// this tree. Any drift — a fourth advisory, a new node, a severity change — fails closed here.
|
|
295
|
+
invariant(
|
|
296
|
+
finding.severity === 'high'
|
|
297
|
+
&& finding.isDirect === false
|
|
298
|
+
&& exactArray(finding.nodes, ['node_modules/npm/node_modules/ip-address'])
|
|
299
|
+
&& exactArray(finding.effects, [])
|
|
300
|
+
&& finding.range === '<=10.3.0'
|
|
301
|
+
&& matchesExactAdvisorySet(finding, 'ip-address', [
|
|
302
|
+
{ source: 1130722, range: '<=10.3.0', url: 'https://github.com/advisories/GHSA-mwp4-54f8-5fhr', severity: 'high' },
|
|
303
|
+
{ source: 1130723, range: '>=10.1.1 <=10.2.1', url: 'https://github.com/advisories/GHSA-4xrf-jv44-h6hh', severity: 'moderate' },
|
|
304
|
+
{ source: 1130724, range: '>=10.1.1 <=10.2.0', url: 'https://github.com/advisories/GHSA-22jq-vg5j-6vgg', severity: 'moderate' },
|
|
305
|
+
]),
|
|
306
|
+
'npm audit ip-address finding differs from the acknowledged bundled preimage',
|
|
307
|
+
)
|
|
308
|
+
return
|
|
309
|
+
}
|
|
310
|
+
if (name === 'undici') {
|
|
311
|
+
// Same situation as ip-address: bundled in npm 11.19.0, no overlay slot yet, fixed 6.28.0
|
|
312
|
+
// exists. Tracked in the cloud-compat baton; exact-shape acknowledgment, drift fails closed.
|
|
313
|
+
invariant(
|
|
314
|
+
finding.severity === 'moderate'
|
|
315
|
+
&& finding.isDirect === false
|
|
316
|
+
&& exactArray(finding.nodes, ['node_modules/npm/node_modules/undici'])
|
|
317
|
+
&& exactArray(finding.effects, [])
|
|
318
|
+
&& finding.range === '<=6.27.0'
|
|
319
|
+
&& matchesExactAdvisorySet(finding, 'undici', [
|
|
320
|
+
{ source: 1130716, range: '<6.28.0', url: 'https://github.com/advisories/GHSA-8xcm-r25x-g524', severity: 'moderate' },
|
|
321
|
+
{ source: 1130727, range: '<6.28.0', url: 'https://github.com/advisories/GHSA-m8rv-5g2x-5cg5', severity: 'moderate' },
|
|
322
|
+
{ source: 1130732, range: '<6.28.0', url: 'https://github.com/advisories/GHSA-v3r7-h72x-cjcm', severity: 'moderate' },
|
|
323
|
+
]),
|
|
324
|
+
'npm audit undici finding differs from the acknowledged bundled preimage',
|
|
325
|
+
)
|
|
326
|
+
return
|
|
327
|
+
}
|
|
279
328
|
if (name === 'tar') {
|
|
280
329
|
invariant(
|
|
281
330
|
finding.severity === 'moderate'
|
|
@@ -1201,7 +1201,7 @@ export function validateInstalledForkCorpus(projectDir) {
|
|
|
1201
1201
|
|| manifest.consumer.executionRuntime.nativeWindowsPolicy !== 'unsupported-fail-closed'
|
|
1202
1202
|
|| JSON.stringify(manifest.consumer.executionRuntime.supportedHostPlatforms) !== JSON.stringify(['darwin', 'linux'])
|
|
1203
1203
|
|| JSON.stringify(manifest.consumer.executionRuntime.windowsCompatibilityEnvironments) !== JSON.stringify(['devcontainer-linux', 'wsl2-linux'])
|
|
1204
|
-
|| JSON.stringify(manifest.consumer.executionRuntime.requiredExecutables) !== JSON.stringify(['bash', 'git', 'jq', 'node', 'python3'])
|
|
1204
|
+
|| JSON.stringify(manifest.consumer.executionRuntime.requiredExecutables) !== JSON.stringify(['bash', 'git', 'jq', 'node', 'perl', 'python3'])
|
|
1205
1205
|
|| JSON.stringify(manifest.consumer.executionRuntime.requiredPathClasses) !== JSON.stringify(['plain', 'space-containing'])
|
|
1206
1206
|
|| bom.payload.executionRuntimeSha256 !== sha256(JSON.stringify(manifest.consumer.executionRuntime))
|
|
1207
1207
|
) throw new Error('installed consumer execution runtime contract is invalid or unbound')
|
|
@@ -40,9 +40,9 @@ const MAX_ARCHIVE_ENTRIES = 5_000
|
|
|
40
40
|
const MAX_ARCHIVE_PATH_BYTES = 256
|
|
41
41
|
const textDecoder = new TextDecoder('utf-8', { fatal: true })
|
|
42
42
|
const NPM_RUNTIME_OVERLAY_ALIAS = 'npm-runtime-brace-expansion-patch'
|
|
43
|
-
const NPM_RUNTIME_OVERLAY_SPEC = 'npm:brace-expansion@5.0.
|
|
43
|
+
const NPM_RUNTIME_OVERLAY_SPEC = 'npm:brace-expansion@5.0.9'
|
|
44
44
|
const NPM_RUNTIME_OVERLAY_PACKAGE = 'brace-expansion'
|
|
45
|
-
const NPM_RUNTIME_OVERLAY_VERSION = '5.0.
|
|
45
|
+
const NPM_RUNTIME_OVERLAY_VERSION = '5.0.9'
|
|
46
46
|
const NPM_RUNTIME_OVERLAY_REPLACED_VERSION = '5.0.7'
|
|
47
47
|
const NPM_RUNTIME_OVERLAY_TARGET = 'node_modules/brace-expansion'
|
|
48
48
|
const NPM_RUNTIME_OVERLAY_CONSUMER = 'node_modules/minimatch'
|
|
@@ -302,7 +302,7 @@ export async function downloadCanonicalNpmTarball(url, { timeoutMs = 30_000 } =
|
|
|
302
302
|
export async function downloadCanonicalNpmSecurityOverlayTarball(url, { timeoutMs = 30_000 } = {}) {
|
|
303
303
|
return downloadCanonicalRegistryTarball(url, {
|
|
304
304
|
label: 'canonical npm security overlay',
|
|
305
|
-
pathPattern: /^\/(?:brace-expansion\/-\/brace-expansion-5\.0\.
|
|
305
|
+
pathPattern: /^\/(?:brace-expansion\/-\/brace-expansion-5\.0\.9|tar\/-\/tar-7\.5\.22)\.tgz$/,
|
|
306
306
|
timeoutMs,
|
|
307
307
|
})
|
|
308
308
|
}
|