@hirobius/design-system 0.8.1

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.
Files changed (111) hide show
  1. package/LICENSE/main.tsx +21 -0
  2. package/README.md +124 -0
  3. package/dist/chunks/TokenDisplayContext-B3gxyQN7.js +95 -0
  4. package/dist/chunks/form-DnGRy27o.js +63 -0
  5. package/dist/cn.js +8 -0
  6. package/dist/contexts.js +133 -0
  7. package/dist/form.js +62 -0
  8. package/dist/hirobius-ui.js +5611 -0
  9. package/dist/manifest.js +28 -0
  10. package/dist/tokens.css +1 -0
  11. package/dist/tokens.js +693 -0
  12. package/dist/types/src/app/components/activity-feed.d.ts +43 -0
  13. package/dist/types/src/app/components/alert.d.ts +18 -0
  14. package/dist/types/src/app/components/asset-img.d.ts +54 -0
  15. package/dist/types/src/app/components/avatar.d.ts +23 -0
  16. package/dist/types/src/app/components/badge.d.ts +20 -0
  17. package/dist/types/src/app/components/breadcrumb.d.ts +26 -0
  18. package/dist/types/src/app/components/button.d.ts +37 -0
  19. package/dist/types/src/app/components/callout.d.ts +23 -0
  20. package/dist/types/src/app/components/card.d.ts +119 -0
  21. package/dist/types/src/app/components/checkbox.d.ts +20 -0
  22. package/dist/types/src/app/components/cinematic-link.d.ts +13 -0
  23. package/dist/types/src/app/components/code-block.d.ts +29 -0
  24. package/dist/types/src/app/components/combobox.d.ts +46 -0
  25. package/dist/types/src/app/components/component-instance-matrix.d.ts +21 -0
  26. package/dist/types/src/app/components/container.d.ts +31 -0
  27. package/dist/types/src/app/components/dialog.d.ts +73 -0
  28. package/dist/types/src/app/components/disclosure.d.ts +32 -0
  29. package/dist/types/src/app/components/divider.d.ts +21 -0
  30. package/dist/types/src/app/components/doc-link-card.d.ts +26 -0
  31. package/dist/types/src/app/components/empty-state.d.ts +24 -0
  32. package/dist/types/src/app/components/error-boundary.d.ts +25 -0
  33. package/dist/types/src/app/components/error-pattern.d.ts +9 -0
  34. package/dist/types/src/app/components/field.d.ts +25 -0
  35. package/dist/types/src/app/components/form.d.ts +106 -0
  36. package/dist/types/src/app/components/foundation-swatch.d.ts +39 -0
  37. package/dist/types/src/app/components/grid.d.ts +65 -0
  38. package/dist/types/src/app/components/heading-stack.d.ts +42 -0
  39. package/dist/types/src/app/components/history-card.d.ts +12 -0
  40. package/dist/types/src/app/components/icon-button.d.ts +23 -0
  41. package/dist/types/src/app/components/icon.d.ts +30 -0
  42. package/dist/types/src/app/components/info-page.d.ts +10 -0
  43. package/dist/types/src/app/components/inline-code.d.ts +12 -0
  44. package/dist/types/src/app/components/inline-link.d.ts +17 -0
  45. package/dist/types/src/app/components/input.d.ts +46 -0
  46. package/dist/types/src/app/components/lab/tokenUtils.d.ts +38 -0
  47. package/dist/types/src/app/components/menu.d.ts +56 -0
  48. package/dist/types/src/app/components/nav-group.d.ts +24 -0
  49. package/dist/types/src/app/components/nav-item.d.ts +21 -0
  50. package/dist/types/src/app/components/not-found-pattern.d.ts +1 -0
  51. package/dist/types/src/app/components/page.d.ts +43 -0
  52. package/dist/types/src/app/components/pagination.d.ts +24 -0
  53. package/dist/types/src/app/components/popover.d.ts +44 -0
  54. package/dist/types/src/app/components/progress.d.ts +25 -0
  55. package/dist/types/src/app/components/radio.d.ts +18 -0
  56. package/dist/types/src/app/components/segmented-control.d.ts +33 -0
  57. package/dist/types/src/app/components/skeleton.d.ts +25 -0
  58. package/dist/types/src/app/components/sketch.d.ts +13 -0
  59. package/dist/types/src/app/components/slider.d.ts +22 -0
  60. package/dist/types/src/app/components/spinner.d.ts +20 -0
  61. package/dist/types/src/app/components/stack.d.ts +39 -0
  62. package/dist/types/src/app/components/stat.d.ts +24 -0
  63. package/dist/types/src/app/components/status-list-item.d.ts +25 -0
  64. package/dist/types/src/app/components/status-tile.d.ts +22 -0
  65. package/dist/types/src/app/components/stepper-field.d.ts +13 -0
  66. package/dist/types/src/app/components/surface-padding.d.ts +18 -0
  67. package/dist/types/src/app/components/surface.d.ts +30 -0
  68. package/dist/types/src/app/components/table.d.ts +40 -0
  69. package/dist/types/src/app/components/tabs.d.ts +27 -0
  70. package/dist/types/src/app/components/tag.d.ts +32 -0
  71. package/dist/types/src/app/components/text-lockup.d.ts +38 -0
  72. package/dist/types/src/app/components/text.d.ts +26 -0
  73. package/dist/types/src/app/components/tile-grid.d.ts +17 -0
  74. package/dist/types/src/app/components/toast.d.ts +56 -0
  75. package/dist/types/src/app/components/toggle.d.ts +18 -0
  76. package/dist/types/src/app/components/token.d.ts +59 -0
  77. package/dist/types/src/app/components/tooltip.d.ts +33 -0
  78. package/dist/types/src/app/context/DemoStateContext.d.ts +21 -0
  79. package/dist/types/src/app/context/FontContext.d.ts +4 -0
  80. package/dist/types/src/app/context/LanguageContext.d.ts +23 -0
  81. package/dist/types/src/app/context/RouterContext.d.ts +61 -0
  82. package/dist/types/src/app/context/TenantContext.d.ts +29 -0
  83. package/dist/types/src/app/context/ThemeContext.d.ts +18 -0
  84. package/dist/types/src/app/context/TokenDisplayContext.d.ts +11 -0
  85. package/dist/types/src/app/context/index.d.ts +19 -0
  86. package/dist/types/src/app/data/manifest-types.d.ts +128 -0
  87. package/dist/types/src/app/design-system/generated-token-refs.d.ts +586 -0
  88. package/dist/types/src/app/design-system/generated-token-values.d.ts +223 -0
  89. package/dist/types/src/app/design-system/theme.d.ts +32 -0
  90. package/dist/types/src/app/design-system/tokens.d.ts +333 -0
  91. package/dist/types/src/app/hooks/useFocusVisible.d.ts +9 -0
  92. package/dist/types/src/app/hooks/useInteractionState.d.ts +27 -0
  93. package/dist/types/src/app/layouts/CaseStudyLayout.d.ts +21 -0
  94. package/dist/types/src/app/layouts/DocLayout.d.ts +16 -0
  95. package/dist/types/src/app/layouts/EmbeddedDocLayoutContext.d.ts +6 -0
  96. package/dist/types/src/app/lib/nav-active.d.ts +16 -0
  97. package/dist/types/src/app/lib/navLevels.d.ts +4 -0
  98. package/dist/types/src/app/pages/hds/HdsSystemDocLayout.d.ts +7 -0
  99. package/dist/types/src/form/hds-form.d.ts +61 -0
  100. package/dist/types/src/form/index.d.ts +30 -0
  101. package/dist/types/src/form/use-hds-form.d.ts +23 -0
  102. package/dist/types/src/index.d.ts +2276 -0
  103. package/dist/types/src/lib/deprecation.d.ts +4 -0
  104. package/dist/types/src/lib/manifest-entry.d.ts +3 -0
  105. package/dist/types/src/lib/utils.d.ts +3 -0
  106. package/dist/variables.css +461 -0
  107. package/hirobius.tokens.json +2220 -0
  108. package/package.json +366 -0
  109. package/protocol/envelope.mjs +201 -0
  110. package/protocol/figma-snapshot.schema.json +190 -0
  111. package/public/hds-manifest.json +11230 -0
package/package.json ADDED
@@ -0,0 +1,366 @@
1
+ {
2
+ "name": "@hirobius/design-system",
3
+ "description": "Hirobius Design Systems Architecture: token-governed React components, documentation surfaces, and distribution tooling.",
4
+ "private": false,
5
+ "version": "0.8.1",
6
+ "engines": {
7
+ "node": ">=20",
8
+ "pnpm": ">=8"
9
+ },
10
+ "type": "module",
11
+ "typeCoverage": {
12
+ "ignoreFiles": [
13
+ "src/app/components/mobius-distortion.ts"
14
+ ]
15
+ },
16
+ "module": "./dist/hirobius-ui.js",
17
+ "types": "./dist/types/src/index.d.ts",
18
+ "sideEffects": [
19
+ "**/*.css"
20
+ ],
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/types/src/index.d.ts",
24
+ "import": "./dist/hirobius-ui.js",
25
+ "default": "./dist/hirobius-ui.js"
26
+ },
27
+ "./tokens.css": "./dist/tokens.css",
28
+ "./variables.css": "./dist/variables.css",
29
+ "./tokens": {
30
+ "types": "./dist/types/src/app/design-system/tokens.d.ts",
31
+ "import": "./dist/tokens.js",
32
+ "default": "./dist/tokens.js"
33
+ },
34
+ "./cn": {
35
+ "types": "./dist/types/src/lib/utils.d.ts",
36
+ "import": "./dist/cn.js",
37
+ "default": "./dist/cn.js"
38
+ },
39
+ "./manifest": {
40
+ "types": "./dist/types/src/lib/manifest-entry.d.ts",
41
+ "import": "./dist/manifest.js",
42
+ "default": "./dist/manifest.js"
43
+ },
44
+ "./contexts": {
45
+ "types": "./dist/types/src/app/context/index.d.ts",
46
+ "import": "./dist/contexts.js",
47
+ "default": "./dist/contexts.js"
48
+ },
49
+ "./form": {
50
+ "types": "./dist/types/src/form/index.d.ts",
51
+ "import": "./dist/form.js",
52
+ "default": "./dist/form.js"
53
+ },
54
+ "./protocol": {
55
+ "import": "./protocol/envelope.mjs",
56
+ "default": "./protocol/envelope.mjs"
57
+ },
58
+ "./package.json": "./package.json"
59
+ },
60
+ "files": [
61
+ "dist",
62
+ "protocol/envelope.mjs",
63
+ "protocol/figma-snapshot.schema.json",
64
+ "hirobius.tokens.json",
65
+ "public/hds-manifest.json"
66
+ ],
67
+ "publishConfig": {
68
+ "registry": "https://registry.npmjs.org",
69
+ "access": "public"
70
+ },
71
+ "peerDependencies": {
72
+ "@hookform/resolvers": "^3.9.0 || ^4.0.0 || ^5.0.0",
73
+ "react": "^18.3.0 || ^19.0.0",
74
+ "react-dom": "^18.3.0 || ^19.0.0",
75
+ "react-hook-form": "^7.0.0",
76
+ "react-router": "^7.0.0",
77
+ "zod": "^3.23.0 || ^4.0.0"
78
+ },
79
+ "peerDependenciesMeta": {
80
+ "react-router": {
81
+ "optional": true
82
+ },
83
+ "react-hook-form": {
84
+ "optional": true
85
+ },
86
+ "zod": {
87
+ "optional": true
88
+ },
89
+ "@hookform/resolvers": {
90
+ "optional": true
91
+ }
92
+ },
93
+ "dependencies": {
94
+ "@radix-ui/react-dialog": "^1.1.15",
95
+ "@radix-ui/react-dropdown-menu": "^2.1.18",
96
+ "@radix-ui/react-popover": "^1.1.17",
97
+ "@radix-ui/react-select": "^2.3.1",
98
+ "@radix-ui/react-slot": "^1.2.4",
99
+ "@radix-ui/react-tabs": "^1.1.13",
100
+ "@radix-ui/react-toast": "^1.2.17",
101
+ "@radix-ui/react-toggle-group": "^1.1.13",
102
+ "class-variance-authority": "^0.7.1",
103
+ "clsx": "^2.1.1",
104
+ "lucide-react": "0.487.0",
105
+ "motion": "12.23.24",
106
+ "tailwind-merge": "^3.5.0"
107
+ },
108
+ "devDependencies": {
109
+ "@arethetypeswrong/cli": "^0.18.4",
110
+ "@axe-core/playwright": "^4.11.1",
111
+ "@changesets/cli": "^2.27.10",
112
+ "@cyclonedx/cyclonedx-npm": "^4.2.1",
113
+ "@hookform/resolvers": "^5.4.0",
114
+ "@lhci/cli": "0.15.1",
115
+ "@microsoft/api-extractor": "7.58.7",
116
+ "@playwright/test": "^1.58.2",
117
+ "@size-limit/file": "^12.1.0",
118
+ "@storybook/addon-a11y": "^8.6.18",
119
+ "@storybook/addon-essentials": "^8.6.14",
120
+ "@storybook/react": "^8.6.18",
121
+ "@storybook/react-vite": "^8.6.18",
122
+ "@tailwindcss/vite": "^4.2.4",
123
+ "@testing-library/dom": "^10.4.0",
124
+ "@testing-library/react": "^16.1.0",
125
+ "@types/react": "^18.3.0",
126
+ "@types/react-dom": "^18.3.0",
127
+ "@types/three": "^0.183.1",
128
+ "@typescript-eslint/eslint-plugin": "^8.59.1",
129
+ "@typescript-eslint/parser": "^8.59.1",
130
+ "@vitejs/plugin-react": "4.7.0",
131
+ "@vitest/coverage-v8": "^4.1.0",
132
+ "acorn": "^8.16.0",
133
+ "acorn-jsx": "^5.3.2",
134
+ "chromatic": "^17.6.0",
135
+ "cors": "^2.8.6",
136
+ "editorconfig-checker": "^6.1.1",
137
+ "eslint": "^10.3.0",
138
+ "eslint-config-prettier": "^10.1.8",
139
+ "eslint-import-resolver-typescript": "^4.4.4",
140
+ "eslint-plugin-import-x": "^4.16.2",
141
+ "eslint-plugin-jsx-a11y": "^6.10.2",
142
+ "eslint-plugin-react": "^7.37.5",
143
+ "eslint-plugin-react-hooks": "^7.1.1",
144
+ "eslint-plugin-tailwindcss": "^3.18.3",
145
+ "express": "^5.2.1",
146
+ "fast-check": "^4.7.0",
147
+ "fuse.js": "^7.1.0",
148
+ "globals": "^17.6.0",
149
+ "husky": "^9.1.7",
150
+ "jscodeshift": "^17.3.0",
151
+ "jsdom": "^29.0.0",
152
+ "knip": "^6.10.0",
153
+ "lint-staged": "^17.0.2",
154
+ "nodemon": "^3.1.14",
155
+ "pixelmatch": "^7.1.0",
156
+ "playwright": "^1.58.2",
157
+ "pngjs": "^7.0.0",
158
+ "prettier": "^3.8.3",
159
+ "publint": "^0.3.21",
160
+ "react": "18.3.1",
161
+ "react-docgen-typescript": "^2.4.0",
162
+ "react-dom": "18.3.1",
163
+ "react-hook-form": "^7.80.0",
164
+ "react-router": "7.13.0",
165
+ "size-limit": "^12.1.0",
166
+ "storybook": "^8.6.18",
167
+ "style-dictionary": "^5.4.0",
168
+ "tailwindcss": "^4.2.4",
169
+ "three": "^0.183.2",
170
+ "type-coverage": "^2.29.7",
171
+ "typescript": "^6.0.2",
172
+ "vite": "6.4.2",
173
+ "vite-bundle-visualizer": "^1.2.1",
174
+ "vitest": "^4.1.0",
175
+ "zod": "^4.4.3",
176
+ "zustand": "^5.0.12"
177
+ },
178
+ "size-limit": [
179
+ {
180
+ "name": "library esm (main barrel)",
181
+ "path": "dist/hirobius-ui.js",
182
+ "limit": "220 kB"
183
+ },
184
+ {
185
+ "name": "library css (tokens + base)",
186
+ "path": "dist/tokens.css",
187
+ "limit": "24 kB"
188
+ },
189
+ {
190
+ "name": "subpath: cn helper",
191
+ "path": "dist/cn.js",
192
+ "limit": "1 kB"
193
+ },
194
+ {
195
+ "name": "subpath: token bridge",
196
+ "path": "dist/tokens.js",
197
+ "limit": "8 kB"
198
+ },
199
+ {
200
+ "name": "subpath: manifest (json-as-esm)",
201
+ "path": "dist/manifest.js",
202
+ "limit": "60 kB"
203
+ }
204
+ ],
205
+ "lint-staged": {
206
+ "*.{ts,tsx,js,jsx,mjs,cjs,json,md,mdx,css,scss,html,yaml,yml}": "prettier --write"
207
+ },
208
+ "scripts": {
209
+ "_comment:a11y-high-value": "The following check:* validators are high-value accessibility checks that catch real violations (check:focus found 1 missing focus class). Kept dormant/manual-only to avoid pre-commit performance regression. Candidates to wire into pretest after CI stability review.",
210
+ "_comment:link-integrity": "check:doc-refs and check:routes both validate internal link integrity (different surfaces: doc refs vs route links). Kept dormant/manual-only to prevent pre-commit cascade.",
211
+ "_comment:security-baseline": "check:security validates OWASP baseline patterns. Dormant/manual-only — candidate for integration into security-focused CI lane, not pretest.",
212
+ "_comment:token-integrity": "check:css-values, check:token-structure validate token system correctness. Dormant/manual-only due to overlapping scope with check:fast and existing token validators.",
213
+ "_comment:editorconfig-version": "check:mojibake pins EC_VERSION=v3.7.0. The editorconfig-checker@6.1.x npm wrapper expects binary v3.7.0 but downloads the latest Go release (v3.8.0, 2026-06-25), so a fresh install fails with a version mismatch (binary != config). Pinning the download to the wrapper's expected version keeps CI + pre-commit green. Bump both together when upgrading the npm package. All editorconfig-checker calls route through check:mojibake.",
214
+ "api:check": "node scripts/audit-component-integrity.mjs --api",
215
+ "api:update": "node scripts/audit-component-integrity.mjs --api --update-baseline",
216
+ "assets:convert": "node scripts/convert-incoming-assets.mjs",
217
+ "assets:manifest": "node scripts/sync-asset-manifest.mjs",
218
+ "audit:bundle": "node scripts/audit-bundle.mjs",
219
+ "audit:deps": "node scripts/audit-deps.mjs",
220
+ "audit:sbom": "node scripts/audit-sbom.mjs",
221
+ "audit:sidecar": "node scripts/generate-security-posture.mjs",
222
+ "audit:style-dictionary": "bash scripts/poc/style-dictionary-poc/run.sh",
223
+ "bridge": "node --env-file=.env.local scripts/hds-bridge.mjs",
224
+ "build": "pnpm sync:health && node scripts/sync-icons.mjs && vite build --configLoader native",
225
+ "build:ssr": "vite build --ssr src/entry-server.tsx --outDir .ssr-cache --configLoader native",
226
+ "build:prerender": "pnpm build && pnpm build:ssr && node scripts/prerender.mjs",
227
+ "build:lib": "vite build -c vite.config.lib.ts && pnpm build:types && node scripts/build-vars-css.mjs && node scripts/embed-fonts.mjs",
228
+ "build:types": "tsc -p tsconfig.dts.json && node scripts/strip-dts-side-effects.mjs",
229
+ "catalog": "node scripts/generate-visual-catalog.mjs",
230
+ "changelog:generate": "node scripts/generate-changelog.mjs",
231
+ "changeset": "changeset",
232
+ "changeset:add": "changeset",
233
+ "changeset:version": "changeset version",
234
+ "codemod": "jscodeshift --parser=tsx --extensions=tsx,ts",
235
+ "storybook": "storybook dev -p 6006",
236
+ "build-storybook": "storybook build",
237
+ "chromatic": "chromatic --exit-zero-on-changes",
238
+ "release": "pnpm build:lib && pnpm smoke:consumer --skip-build && changeset publish",
239
+ "check": "pnpm check:full",
240
+ "check:a11y": "pnpm lint --rule '{\"jsx-a11y/alt-text\":\"error\",\"jsx-a11y/img-redundant-alt\":\"error\"}'",
241
+ "check:assets": "node scripts/check-asset-manifest.mjs",
242
+ "check:attributions": "node scripts/check-attributions.mjs",
243
+ "check:binding-drift": "node scripts/check-binding-drift.mjs",
244
+ "check:brand": "node scripts/check-brand.mjs",
245
+ "check:breakpoints": "node scripts/check-hardcoded-breakpoints.mjs",
246
+ "check:colors": "node scripts/check-hardcoded-colors.mjs",
247
+ "check:contrast": "node scripts/check-contrast.mjs",
248
+ "check:css": "node scripts/check-css-integrity.mjs",
249
+ "check:css-values": "node scripts/check-style-discipline.mjs --css-values-only",
250
+ "check:dimensions": "node scripts/check-dimensions.mjs",
251
+ "check:doc-refs": "node scripts/check-link-integrity.mjs --doc-refs-only",
252
+ "check:doc-structure": "node scripts/check-doc-structure.mjs",
253
+ "check:docs": "node scripts/audit-component-integrity.mjs --docs && node scripts/check-frozen-demos.mjs && node scripts/check-token-descriptions.mjs --no-missing --quality",
254
+ "check:exemptions": "node scripts/check-exemptions.mjs",
255
+ "check:fast": "node scripts/validate-manifest.mjs && node scripts/check-manifest-drift.mjs && node scripts/sync-asset-manifest.mjs && node scripts/build-tokens.mjs && node scripts/build-roadmap-data.mjs && node scripts/verify-tokens.mjs && node scripts/audit-tokens.mjs --full && pnpm typecheck && node scripts/check-css-integrity.mjs && node scripts/audit-component-integrity.mjs --tokens && pnpm check:docs && node scripts/check-ref-forwarding.mjs && node scripts/check-hardcoded-spacing.mjs && node scripts/check-dimensions.mjs && node scripts/check-hardcoded-breakpoints.mjs && node scripts/check-typography-discipline.mjs && pnpm check:mojibake && node scripts/check-mono-roles.mjs && node scripts/check-style-discipline.mjs --style-props-only && node scripts/check-tier-bypass.mjs && node scripts/check-link-integrity.mjs --doc-refs-only && node scripts/check-link-integrity.mjs --route-links-only && node scripts/check-brand.mjs && node scripts/check-registry.mjs && node scripts/check-asset-manifest.mjs && node scripts/check-template-source-of-truth.mjs",
256
+ "check:figma-snapshot": "node scripts/test-figma-masters-snapshot.mjs",
257
+ "check:figma-snapshot:update": "node scripts/test-figma-masters-snapshot.mjs --update",
258
+ "check:focus": "node scripts/check-focus-states.mjs",
259
+ "check:font-files": "node scripts/check-typography-discipline.mjs --font-files-only",
260
+ "check:fonts": "node scripts/check-typography-discipline.mjs --fonts-only",
261
+ "check:forbidden-overrides": "node scripts/audit-tokens.mjs --forbidden",
262
+ "check:format": "pnpm exec lint-staged",
263
+ "check:full": "node scripts/validate-manifest.mjs && node scripts/check-manifest-drift.mjs && node scripts/sync-asset-manifest.mjs && node scripts/build-tokens.mjs && node scripts/verify-tokens.mjs && node scripts/audit-tokens.mjs --full && pnpm typecheck && node scripts/check-css-integrity.mjs && node scripts/audit-component-integrity.mjs --tokens && node scripts/audit-pages.mjs && pnpm check:docs && node scripts/check-doc-structure.mjs && node scripts/check-contrast.mjs && node scripts/check-focus-states.mjs && node scripts/check-reduced-motion.mjs && node scripts/check-ref-forwarding.mjs && node scripts/check-hardcoded-spacing.mjs && node scripts/check-dimensions.mjs && node scripts/check-hardcoded-breakpoints.mjs && node scripts/check-unresponsive-grids.mjs && node scripts/check-page-shell.mjs && node scripts/check-motion.mjs && node scripts/check-typography-discipline.mjs && pnpm check:mojibake && node scripts/check-mono-roles.mjs && node scripts/check-style-discipline.mjs && node scripts/check-hardcoded-colors.mjs && node scripts/check-tier-bypass.mjs && node scripts/check-token-structure.mjs && node scripts/check-link-integrity.mjs && node scripts/check-og-meta.mjs && node scripts/check-asset-manifest.mjs && node scripts/check-security-baseline.mjs && node scripts/check-attributions.mjs && node scripts/check-exemptions.mjs && node scripts/check-brand.mjs && node scripts/check-registry.mjs && node scripts/audit-component-integrity.mjs --api && node scripts/check-token-descriptions.mjs --no-missing && node scripts/check-token-renames.mjs",
264
+ "check:ghost-tokens": "node scripts/audit-tokens.mjs --full",
265
+ "check:grids": "node scripts/check-unresponsive-grids.mjs",
266
+ "check:inline-styles": "node scripts/check-style-discipline.mjs --inline-only",
267
+ "check:knip": "knip",
268
+ "check:knip-ratchet": "knip --max-issues 60",
269
+ "check:licenses": "node scripts/check-licenses.mjs",
270
+ "check:lockfile": "pnpm install --frozen-lockfile --offline --prefer-offline --ignore-scripts --silent 2>/dev/null || (echo 'Lockfile drift: run pnpm install' && exit 1)",
271
+ "check:manifest-drift": "node scripts/check-manifest-drift.mjs",
272
+ "check:micromotion": "node scripts/check-motion.mjs",
273
+ "check:mojibake": "EC_VERSION=v3.7.0 pnpm exec editorconfig-checker",
274
+ "check:mono-roles": "node scripts/check-mono-roles.mjs",
275
+ "check:motion": "node scripts/check-reduced-motion.mjs",
276
+ "check:page-shell": "node scripts/check-page-shell.mjs",
277
+ "check:refs": "node scripts/check-ref-forwarding.mjs",
278
+ "check:registry": "node scripts/check-registry.mjs",
279
+ "check:release": "pnpm check:full && node scripts/check-style-discipline.mjs && pnpm build && pnpm perf:budget && pnpm test:a11y && pnpm test:visual && pnpm test:responsive && pnpm test:collision && pnpm check:size",
280
+ "check:routes": "node scripts/check-link-integrity.mjs --route-links-only",
281
+ "check:secrets": "node scripts/check-secrets.mjs",
282
+ "check:security": "node scripts/check-security-baseline.mjs",
283
+ "check:semantic-report": "node scripts/audit-tokens.mjs --report-only",
284
+ "check:size": "pnpm build:lib && size-limit",
285
+ "check:spacing": "node scripts/check-hardcoded-spacing.mjs",
286
+ "check:style-props": "node scripts/check-style-discipline.mjs --style-props-only",
287
+ "check:tailwind": "pnpm lint --rule '{\"tailwindcss/no-custom-classname\":\"error\"}'",
288
+ "check:tailwind-arbitrary": "pnpm lint --rule '{\"tailwindcss/no-arbitrary-value\":\"error\"}'",
289
+ "check:template-sot": "node scripts/check-template-source-of-truth.mjs",
290
+ "check:tier-bypass": "node scripts/check-tier-bypass.mjs",
291
+ "check:token-descriptions": "node scripts/check-token-descriptions.mjs --no-missing",
292
+ "check:token-renames": "node scripts/check-token-renames.mjs",
293
+ "check:token-structure": "node scripts/check-token-structure.mjs",
294
+ "check:tokens": "node scripts/check-hardcoded-colors.mjs && pnpm lint --rule '{\"tailwindcss/no-custom-classname\":\"error\"}' && node scripts/audit-tokens.mjs --forbidden && node scripts/check-tier-bypass.mjs && node scripts/check-hardcoded-spacing.mjs && node scripts/check-typography-discipline.mjs --fonts-only",
295
+ "check:type-coverage": "pnpm exec type-coverage --at-least 99.9",
296
+ "closure:plan": "node scripts/run-gates.mjs --channel pre-commit --emit-inventory docs/guardrails/full-strictness-inventory.json && node scripts/generate-closure-plan.mjs",
297
+ "closure:plan:check": "node scripts/generate-closure-plan.mjs --check",
298
+ "dev": "node scripts/generate-manifest.mjs && node scripts/sync-asset-manifest.mjs && node scripts/generate-component-api.mjs && node scripts/sync-icons.mjs && node scripts/build-tokens.mjs && node scripts/build-roadmap-data.mjs && vite --configLoader native",
299
+ "docs:api": "node scripts/generate-component-api.mjs",
300
+ "docs:changelogs": "node scripts/generate-component-changelogs.mjs",
301
+ "docs:llms": "node scripts/generate-llms-txt.mjs",
302
+ "figma-variables": "node scripts/build-figma-variables.mjs",
303
+ "figma:bridge:smoke": "node scripts/figma-bridge-smoke.mjs",
304
+ "figma:diff": "node scripts/figma-diff.mjs",
305
+ "figma:snapshot": "node scripts/normalize-figma-snapshot.mjs",
306
+ "figma:stream": "node scripts/llm-stream-bridge.mjs",
307
+ "guardrail:firing-stats": "node scripts/refresh-firing-stats.mjs",
308
+ "heal": "node scripts/self-heal.mjs",
309
+ "heal:smoke": "node scripts/self-heal.mjs --smoke",
310
+ "health-commit": "pnpm check:semantic-report && node scripts/print-health-commit.mjs",
311
+ "icons:sync": "node scripts/sync-icons.mjs",
312
+ "knip": "knip",
313
+ "lint": "eslint src scripts validators tests",
314
+ "lint:fix": "eslint src scripts validators tests --fix",
315
+ "llms:generate": "node scripts/generate-llms-txt.mjs",
316
+ "manifest:generate": "node scripts/generate-manifest.mjs && node scripts/generate-component-api.mjs && node scripts/enrich-manifest.mjs",
317
+ "manifest:project": "node scripts/generate-manifest-projection.mjs",
318
+ "nav:generate": "node scripts/generate-nav-model.mjs",
319
+ "perf:budget": "node -e \"require('fs').readdirSync('.lighthouseci').filter(f=>f.startsWith('lhr-')).forEach(f=>require('fs').unlinkSync('.lighthouseci/'+f))\" 2>/dev/null; lhci collect --config=.lighthouserc.json && lhci assert --config=.lighthouserc.json; find . -maxdepth 1 -type d -name 'C:*' -exec rm -rf {} + 2>/dev/null; true",
320
+ "prebuild": "node scripts/validate-manifest.mjs",
321
+ "prebuild:lib": "node scripts/generate-component-api.mjs",
322
+ "pretest": "node scripts/validate-manifest.mjs && node scripts/check-manifest-drift.mjs && node scripts/check-manifest-schema-semver.mjs && node scripts/audit-component-integrity.mjs --completeness && node scripts/check-source-canon.mjs && node scripts/check-binding-drift.mjs && node scripts/test-figma-masters-snapshot.mjs && node scripts/test-doc-pages-snapshot.mjs && node scripts/check-registry.mjs && node scripts/check-tenant-tokens.mjs && knip --no-exit-code",
323
+ "promote": "node scripts/promote.mjs",
324
+ "roadmap:data": "node scripts/build-roadmap-data.mjs && node scripts/verify-roadmap-sync.mjs",
325
+ "roadmap:verify": "node scripts/verify-roadmap-sync.mjs",
326
+ "roadmap:watch": "node scripts/watch-roadmap.mjs",
327
+ "scaffold:component": "node scripts/scaffold-component.mjs",
328
+ "scaffold:tenant": "node scripts/scaffold-tenant.mjs",
329
+ "sitemap:generate": "node scripts/generate-sitemap.mjs",
330
+ "size-limit": "size-limit --config .size-limit.cjs",
331
+ "smoke:consumer": "node scripts/smoke-consumer.mjs",
332
+ "sync": "node scripts/build-tokens.mjs && node scripts/audit-tokens.mjs --forbidden && node scripts/build-handoff.mjs && node scripts/build-design-md.mjs && node scripts/build-figma-variables.mjs",
333
+ "sync:health": "node scripts/generate-manifest.mjs && node scripts/generate-component-api.mjs && node scripts/enrich-manifest.mjs && node scripts/sync-asset-manifest.mjs && node scripts/build-tokens.mjs && node scripts/audit-tokens.mjs --report-only && node scripts/build-design-md.mjs && node scripts/build-roadmap-data.mjs && node scripts/verify-roadmap-sync.mjs",
334
+ "test": "vitest run --passWithNoTests",
335
+ "test:a11y": "playwright test tests/a11y.spec.ts",
336
+ "test:collision": "playwright test tests/collision.spec.ts",
337
+ "test:compiler": "node -e \"import('./scripts/hds-jsx-compiler.mjs').then(m => console.log(JSON.stringify(m.compile(process.argv[1]), null, 2)))\" --",
338
+ "test:coverage": "vitest run --coverage",
339
+ "test:figma": "npx tsx scripts/figma-sync.ts",
340
+ "test:layout": "node scripts/check-route-coverage.mjs && playwright test tests/layout-integrity.spec.ts",
341
+ "test:phase1": "node scripts/test-phase1.mjs",
342
+ "test:prompts": "node scripts/test-prompt-regression.mjs",
343
+ "test:responsive": "playwright test tests/responsive.spec.ts",
344
+ "test:visual": "playwright test tests/visual.spec.ts",
345
+ "test:visual:update": "playwright test tests/visual.spec.ts --update-snapshots",
346
+ "test:watch": "vitest",
347
+ "tokens": "node scripts/generate-manifest.mjs && node scripts/build-tokens.mjs && node scripts/audit-tokens.mjs --forbidden && node scripts/check-typography-discipline.mjs --overrides-only && node scripts/sync-hds-registry.mjs && node scripts/build-handoff.mjs && node scripts/build-design-md.mjs && node scripts/generate-llms-txt.mjs",
348
+ "tokens:audit": "node scripts/audit-component-integrity.mjs --tokens",
349
+ "tokens:audit:pages": "node scripts/audit-pages.mjs",
350
+ "tokens:build": "node scripts/build-hds-tokens.mjs",
351
+ "tokens:index": "node scripts/build-token-index.mjs",
352
+ "tokens:verify": "node scripts/build-tokens.mjs && node scripts/verify-tokens.mjs",
353
+ "typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
354
+ "ui:fix": "node scripts/generate-to-figma.mjs --fix",
355
+ "ui:gen": "node scripts/generate-to-figma.mjs",
356
+ "ui:lint": "node scripts/ui-lint.mjs",
357
+ "ui:masters": "node scripts/build-figma-masters.mjs",
358
+ "validate:manifest": "node scripts/validate-manifest.mjs",
359
+ "visual-ingest": "node scripts/visual-ingest.mjs",
360
+ "watch:guardrails": "nodemon --watch CLAUDE.md --watch .cursorrules --watch eslint.config.js --watch .github/workflows -e md,json,js,yml,yaml --exec \"node scripts/audit-guardrails.js\"",
361
+ "watch:metrics": "nodemon --watch src/app/components --watch src/app/pages --watch src/app/design-system --watch src/app/styles -e tsx,ts,css --exec \"node scripts/audit-tokens.mjs --full && node scripts/generate-manifest.mjs\"",
362
+ "loop:validate": "node scripts/loop/loop-cli.mjs validate",
363
+ "loop:next": "node scripts/loop/loop-cli.mjs next",
364
+ "loop:status": "node scripts/loop/loop-cli.mjs status"
365
+ }
366
+ }
@@ -0,0 +1,201 @@
1
+ /**
2
+ * protocol/envelope.mjs
3
+ *
4
+ * Message-envelope protocol for bridge↔plugin traffic. Build unit p5-1.
5
+ *
6
+ * Envelope shape:
7
+ * {
8
+ * id: string (UUID v4)
9
+ * type: string (verb, e.g. "selection.update")
10
+ * payload: object
11
+ * timestamp: number (ms since epoch)
12
+ * hmac: string (HMAC-SHA256(secret, stableStringify({id,type,timestamp,payload})))
13
+ * }
14
+ *
15
+ * The Figma plugin sandbox cannot import from this file. The mirror
16
+ * implementation lives at `figma-agent-plugin/protocol-envelope.js` and
17
+ * MUST stay byte-equivalent in HMAC output for the same inputs.
18
+ *
19
+ * Schema decisions (also documented in the unit's commit body):
20
+ * - Clock-skew tolerance: ±60s on either side of now.
21
+ * - Hard expiry: 5 minutes (300_000 ms) past `timestamp`.
22
+ * - Replay-protection set: in-memory Map, FIFO-evicted at 1000 entries.
23
+ *
24
+ * Hard rules (CLAUDE.md / OPERATOR_BRIEF.md):
25
+ * - No new npm dependencies; native Node crypto only.
26
+ * - This file is the protocol library only — wiring the envelope into
27
+ * hds-bridge.mjs / plugin code.js belongs to p5-2 and p5-3.
28
+ */
29
+
30
+ import crypto from 'node:crypto';
31
+
32
+ export const CLOCK_SKEW_MS = 60_000; // ±60s tolerance for future timestamps
33
+ export const MAX_AGE_MS = 5 * 60_000; // 5 min hard expiry
34
+ export const REPLAY_SET_LIMIT = 1000; // FIFO eviction beyond this
35
+
36
+ // ── stable serialization ───────────────────────────────────────────────────
37
+
38
+ /**
39
+ * Deterministic JSON serializer: object keys sorted lexicographically at
40
+ * every level, no whitespace. Used as the HMAC pre-image so the Node-side
41
+ * and plugin-side implementations produce identical signatures.
42
+ */
43
+ export function stableStringify(value) {
44
+ if (value === null || typeof value !== 'object') {
45
+ return JSON.stringify(value);
46
+ }
47
+ if (Array.isArray(value)) {
48
+ return '[' + value.map((v) => stableStringify(v)).join(',') + ']';
49
+ }
50
+ const keys = Object.keys(value).sort();
51
+ const parts = [];
52
+ for (const k of keys) {
53
+ const v = value[k];
54
+ if (v === undefined) continue; // mirror JSON.stringify behavior
55
+ parts.push(JSON.stringify(k) + ':' + stableStringify(v));
56
+ }
57
+ return '{' + parts.join(',') + '}';
58
+ }
59
+
60
+ // ── helpers ────────────────────────────────────────────────────────────────
61
+
62
+ function computeHmac(secret, preimage) {
63
+ return crypto.createHmac('sha256', String(secret)).update(preimage).digest('hex');
64
+ }
65
+
66
+ function preimageOf(envelope) {
67
+ // HMAC binds the four schema fields. Order doesn't matter — stableStringify
68
+ // sorts keys — but be explicit so the contract is readable.
69
+ return stableStringify({
70
+ id: envelope.id,
71
+ payload: envelope.payload,
72
+ timestamp: envelope.timestamp,
73
+ type: envelope.type,
74
+ });
75
+ }
76
+
77
+ function timingSafeEqualHex(a, b) {
78
+ if (typeof a !== 'string' || typeof b !== 'string') return false;
79
+ if (a.length !== b.length) return false;
80
+ try {
81
+ return crypto.timingSafeEqual(Buffer.from(a, 'hex'), Buffer.from(b, 'hex'));
82
+ } catch {
83
+ return false;
84
+ }
85
+ }
86
+
87
+ // ── replay-protection set (in-memory, module-scoped) ──────────────────────
88
+
89
+ const _seenIds = new Map(); // id → timestamp; insertion-ordered for FIFO eviction
90
+
91
+ function recordSeen(id) {
92
+ if (_seenIds.has(id)) {
93
+ // refresh insertion order is not desired — keep original entry
94
+ return;
95
+ }
96
+ _seenIds.set(id, Date.now());
97
+ while (_seenIds.size > REPLAY_SET_LIMIT) {
98
+ const firstKey = _seenIds.keys().next().value;
99
+ _seenIds.delete(firstKey);
100
+ }
101
+ }
102
+
103
+ /** Test/diagnostics helper — clears the replay-protection set. */
104
+ export function _resetReplaySet() {
105
+ _seenIds.clear();
106
+ }
107
+
108
+ /** Test/diagnostics helper — current replay-set size. */
109
+ export function _replaySetSize() {
110
+ return _seenIds.size;
111
+ }
112
+
113
+ // ── public API ─────────────────────────────────────────────────────────────
114
+
115
+ /**
116
+ * Build a signed envelope.
117
+ *
118
+ * @param {string} type Verb, e.g. "selection.update".
119
+ * @param {object} payload Arbitrary serializable object.
120
+ * @param {string} secret Shared secret (UTF-8 string).
121
+ * @returns {object} Envelope ready for transport.
122
+ */
123
+ export function createEnvelope(type, payload, secret) {
124
+ if (typeof type !== 'string' || type.length === 0) {
125
+ throw new TypeError('createEnvelope: type must be a non-empty string');
126
+ }
127
+ if (payload === null || typeof payload !== 'object') {
128
+ throw new TypeError('createEnvelope: payload must be an object');
129
+ }
130
+ if (typeof secret !== 'string' || secret.length === 0) {
131
+ throw new TypeError('createEnvelope: secret must be a non-empty string');
132
+ }
133
+ const envelope = {
134
+ id: crypto.randomUUID(),
135
+ type,
136
+ payload,
137
+ timestamp: Date.now(),
138
+ };
139
+ envelope.hmac = computeHmac(secret, preimageOf(envelope));
140
+ return envelope;
141
+ }
142
+
143
+ /**
144
+ * Verify a received envelope.
145
+ *
146
+ * @param {object} envelope
147
+ * @param {string} secret
148
+ * @param {{ now?: number }} [options] Optional clock override (testing).
149
+ * @returns {{ ok: true } | { ok: false, code: string, message?: string }}
150
+ */
151
+ export function verifyEnvelope(envelope, secret, options = {}) {
152
+ if (envelope === null || typeof envelope !== 'object') {
153
+ return { ok: false, code: 'MALFORMED', message: 'envelope is not an object' };
154
+ }
155
+ const { id, type, payload, timestamp, hmac } = envelope;
156
+ if (typeof id !== 'string' || id.length === 0) {
157
+ return { ok: false, code: 'MALFORMED', message: 'missing id' };
158
+ }
159
+ if (typeof type !== 'string' || type.length === 0) {
160
+ return { ok: false, code: 'MALFORMED', message: 'missing type' };
161
+ }
162
+ if (payload === null || typeof payload !== 'object') {
163
+ return { ok: false, code: 'MALFORMED', message: 'missing or invalid payload' };
164
+ }
165
+ if (typeof timestamp !== 'number' || !Number.isFinite(timestamp)) {
166
+ return { ok: false, code: 'MALFORMED', message: 'missing or invalid timestamp' };
167
+ }
168
+ if (typeof hmac !== 'string' || hmac.length === 0) {
169
+ return { ok: false, code: 'MALFORMED', message: 'missing hmac' };
170
+ }
171
+ if (typeof secret !== 'string' || secret.length === 0) {
172
+ return { ok: false, code: 'MALFORMED', message: 'verifier secret must be non-empty string' };
173
+ }
174
+
175
+ const now = typeof options.now === 'number' ? options.now : Date.now();
176
+
177
+ // Future-skew check (timestamp claims to be too far in the future)
178
+ if (timestamp - now > CLOCK_SKEW_MS) {
179
+ return { ok: false, code: 'EXPIRED', message: 'timestamp is in the future beyond clock-skew tolerance' };
180
+ }
181
+ // Past expiry check (timestamp older than MAX_AGE_MS)
182
+ if (now - timestamp > MAX_AGE_MS) {
183
+ return { ok: false, code: 'EXPIRED', message: 'envelope older than max-age' };
184
+ }
185
+
186
+ // HMAC check
187
+ const expected = computeHmac(secret, preimageOf(envelope));
188
+ if (!timingSafeEqualHex(expected, hmac)) {
189
+ return { ok: false, code: 'HMAC_MISMATCH', message: 'hmac signature does not match' };
190
+ }
191
+
192
+ // Replay check — must come after HMAC (don't pollute the set with junk)
193
+ if (_seenIds.has(id)) {
194
+ return { ok: false, code: 'REPLAY', message: 'envelope id already seen' };
195
+ }
196
+ recordSeen(id);
197
+
198
+ return { ok: true };
199
+ }
200
+
201
+ export default { createEnvelope, verifyEnvelope, stableStringify };