{"_id":"@4cloudguru/cloud-suite-ui","_rev":"9-a5c6917c196fc05db62dd012c65f1de6","name":"@4cloudguru/cloud-suite-ui","dist-tags":{"latest":"0.13.1"},"versions":{"0.9.0":{"name":"@4cloudguru/cloud-suite-ui","version":"0.9.0","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.9.0","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"6ab6a4fa8dbe11baa8e065f552fb0a7fe6505622","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.9.0.tgz","fileCount":7,"integrity":"sha512-5N7z3FosJuJjZVHJOhZC9QPHk4dd4WktAblpP6+hHhI0GPZmfe04olwoqm+dO88OQHjeu8VwXvgXOfpM8vJy+Q==","signatures":[{"sig":"MEQCID4x040rGPU6xgEmhdz2ZlrrkCDwgjqt8oWr/nF+3CdXAiBSr7yACPM5niXHPJcOOd4rHw+Cmnmf3cfj1n04tw1JBQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.9.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":175801},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.9.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"dragonthegn","email":"stbacon@gmail.com"},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.9.0.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-5N7z3FosJuJjZVHJOhZC9QPHk4dd4WktAblpP6+hHhI0GPZmfe04olwoqm+dO88OQHjeu8VwXvgXOfpM8vJy+Q==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.16.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.9.0_1786509865565_0.8754716695296476","host":"s3://npm-registry-packages-npm-production"}},"0.9.1":{"name":"@4cloudguru/cloud-suite-ui","version":"0.9.1","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.9.1","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"6b881223af0eff0e110321d228e5db00332a27f4","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.9.1.tgz","fileCount":7,"integrity":"sha512-o7/WnYNZHrTeH/FdrVpRmW8nQQWWcOiVr28iWbtgHXT5q16EEV+DJUyf9H1PhJ4RIQfur9dvycMVK+rZCV9eaA==","signatures":[{"sig":"MEYCIQCc35Z7IYdAvf0pIlSVYEcZ5VJqjoPdsgL/fJ6C4HgdSAIhAI4YcZuBMAElw/qVjoj64ZEB85xFvV16fy3merQeu+/S","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.9.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":175801},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.9.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.9.1.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-o7/WnYNZHrTeH/FdrVpRmW8nQQWWcOiVr28iWbtgHXT5q16EEV+DJUyf9H1PhJ4RIQfur9dvycMVK+rZCV9eaA==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.17.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.9.1_1786570354351_0.30413834812912466","host":"s3://npm-registry-packages-npm-production"}},"0.9.2":{"name":"@4cloudguru/cloud-suite-ui","version":"0.9.2","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.9.2","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"887003092acffefcb7d4b728e021e6b76dc0f402","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.9.2.tgz","fileCount":7,"integrity":"sha512-liVibvXRAzV3/U4IuHcXf/XsWqs8auq/wTtaD1xKJjGiOGs5LCcykJaHixAs+OSQFjKhE38tPPDna2F0xLl5Gw==","signatures":[{"sig":"MEQCIGJCWMoF7FwCirD5AdsUYRgHnAJN9vdx+SincgPdenv0AiA1ocRw8dnXKyZWzkP5MG9tHX1qv0t467wxITS9o7jKVw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.9.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":175801},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.9.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.9.2.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-liVibvXRAzV3/U4IuHcXf/XsWqs8auq/wTtaD1xKJjGiOGs5LCcykJaHixAs+OSQFjKhE38tPPDna2F0xLl5Gw==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.17.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.9.2_1787275887772_0.24218242264646372","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"@4cloudguru/cloud-suite-ui","version":"0.10.0","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.10.0","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"2c3acb88c305703c06be8cad25181a7e935f7c03","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.10.0.tgz","fileCount":7,"integrity":"sha512-zdzh4CqCEthXgg7dVp9xvumtWPjHhYbG7b6e6WFuYU52CG/2XOdHtAsb5PuYl1SW0Qc4LOJZSCzlnudyyAVeuQ==","signatures":[{"sig":"MEYCIQDT2J4vSHur49Sz1B+lg6wXj7gqvRFn9H3O+ES04NNawgIhAI7XqlJUYnTuVVzUIFHbXmquYQY98PpfIbtqRiUY8hLQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.10.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":189392},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.10.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.10.0.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-zdzh4CqCEthXgg7dVp9xvumtWPjHhYbG7b6e6WFuYU52CG/2XOdHtAsb5PuYl1SW0Qc4LOJZSCzlnudyyAVeuQ==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.17.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.10.0_1787336782763_0.8100114832694394","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"@4cloudguru/cloud-suite-ui","version":"0.11.0","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.11.0","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"074d172254457871d65055ade028dae6ea041225","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.11.0.tgz","fileCount":7,"integrity":"sha512-UCRSHXLefQ7yIW6fpIESI/CWIc7GZD8wsHWRi987lzyFouLMJmV688MgNVo5XKN3H3qzlpPOvUcGFrnvM4BiWA==","signatures":[{"sig":"MEYCIQDLPF9gXF+Bh+N38yYPSeTd/DPg4LTV8lvy5Ajo1pbEjQIhAKYGjZfKE6j0jnMY/m7wkkU2kb1S3Z63S95TDknrGhxQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.11.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":194648},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.11.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.11.0.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-UCRSHXLefQ7yIW6fpIESI/CWIc7GZD8wsHWRi987lzyFouLMJmV688MgNVo5XKN3H3qzlpPOvUcGFrnvM4BiWA==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.17.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.11.0_1787934583620_0.33639241483730564","host":"s3://npm-registry-packages-npm-production"}},"0.11.1":{"name":"@4cloudguru/cloud-suite-ui","version":"0.11.1","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.11.1","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"7564fa76ed8ddbaf4674e156d807902dc20aadc6","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.11.1.tgz","fileCount":7,"integrity":"sha512-yJmVZzC3TCerdaTZpwn0QSRGQXzEcxsWxUnEtGNS/Np4YynnEs3q1tGn+TNRgAI+yV8e72szoSDGOM1KlLnxrg==","signatures":[{"sig":"MEUCIQD7jxNQgAkXAN2loR67izCX9L5DveXg0JHGP9gnHhtmLAIgLJhshOLNf6YN9k/7pFLjOqsCU0Mp4XpXZjO+9klTNeI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.11.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":195801},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.11.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.11.1.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-yJmVZzC3TCerdaTZpwn0QSRGQXzEcxsWxUnEtGNS/Np4YynnEs3q1tGn+TNRgAI+yV8e72szoSDGOM1KlLnxrg==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.17.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.11.1_1788077724442_0.6834097622509439","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"@4cloudguru/cloud-suite-ui","version":"0.12.0","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.12.0","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"d5e210846ae1c70b84b671540444e016c3b26bdd","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.12.0.tgz","fileCount":7,"integrity":"sha512-op+TwLgtS0SBZ2fIsX45ijO6VtEnNJoQn5R9RsjJM9x1HElBYl8IC4euDAR28xB6chsEV/FB61AuS9zNsQ6VWw==","signatures":[{"sig":"MEUCIQCONL4tU9XZJBccDryekXSCZ1bCPovm7tfCGdoKvFSUdAIgNd2in0F4XOYS8KPgIfBHEOrQ8UpxJCBvVhGLuLK4A+Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.12.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":198096},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.12.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.12.0.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-op+TwLgtS0SBZ2fIsX45ijO6VtEnNJoQn5R9RsjJM9x1HElBYl8IC4euDAR28xB6chsEV/FB61AuS9zNsQ6VWw==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.17.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.12.0_1788113327542_0.8984448106429817","host":"s3://npm-registry-packages-npm-production"}},"0.13.0":{"name":"@4cloudguru/cloud-suite-ui","version":"0.13.0","license":"Apache-2.0","_id":"@4cloudguru/cloud-suite-ui@0.13.0","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"dist":{"shasum":"1a6300a369f162bb7ca841ed82db49f850904290","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.13.0.tgz","fileCount":7,"integrity":"sha512-MzLanaU2dRlJ3tiQdGrRA0j1JA7jUYGcfM5JmtbUsAoVR4OdO/5AryjbDBdhTTDfbI25UlDh7xqu6Pdi4qJ0VA==","signatures":[{"sig":"MEUCICtIgFZBCy8vukNkPEC0UxxiYgLFYQRltXmduETLzNTtAiEAncLaa/n2jI6tQeoqdfeIYVuUwxmM+PufN3xfv1YfCpY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.13.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":198096},"main":"./dist/index.js","type":"module","_from":"file:4cloudguru-cloud-suite-ui-0.13.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=22.0.0 <25"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"private":false,"scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup && node scripts/strip-sourcemap-sources.mjs","typecheck":"tsc --noEmit","commitlint":"commitlint","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.13.0.tgz","overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"_integrity":"sha512-MzLanaU2dRlJ3tiQdGrRA0j1JA7jUYGcfM5JmtbUsAoVR4OdO/5AryjbDBdhTTDfbI25UlDh7xqu6Pdi4qJ0VA==","repository":{"url":"git+https://github.com/4cloudguru/cloud-suite-ui.git","type":"git"},"_npmVersion":"11.17.0","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","react":"^19.2.8","vitest":"^4.1.7","i18next":"^26.3.6","happy-dom":"^20.11.1","react-dom":"^19.2.8","typescript":"^5.7.2","@types/node":"^26.1.2","@types/react":"^19.2.18","@mui/material":"^9.0.1","react-i18next":"^17.0.11","@emotion/react":"^11.14.0","@commitlint/cli":"^21.2.1","@emotion/styled":"^11.14.1","@types/react-dom":"^19.2.4","react-router-dom":"^7.18.1","@mui/icons-material":"^9.2.0","@vitest/coverage-v8":"^4.1.7","@testing-library/dom":"^10.4.1","@vitejs/plugin-react":"^6.0.5","@testing-library/react":"^16.3.2","@testing-library/jest-dom":"^7.0.0","@testing-library/user-event":"^14.6.1","@commitlint/config-conventional":"^21.2.0"},"peerDependencies":{"react":"^19.0.0","i18next":"^24.0.0 || ^26.0.0","react-dom":"^19.0.0","@mui/material":"^9.0.0","react-i18next":"^15.0.0 || ^17.0.0","@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","react-router-dom":"^6.0.0 || ^7.0.0","@mui/icons-material":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cloud-suite-ui_0.13.0_1788192225675_0.5158232527343334","host":"s3://npm-registry-packages-npm-production"}},"0.13.1":{"name":"@4cloudguru/cloud-suite-ui","version":"0.13.1","description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","license":"Apache-2.0","private":false,"publishConfig":{"registry":"https://registry.npmjs.org","access":"public"},"repository":{"type":"git","url":"git+https://github.com/4cloudguru/cloud-suite-ui.git"},"type":"module","engines":{"node":">=22.0.0 <25"},"main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"sideEffects":false,"scripts":{"build":"tsup && node scripts/strip-sourcemap-sources.mjs","dev":"tsup --watch","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","commitlint":"commitlint"},"peerDependencies":{"@emotion/react":"^11.0.0","@emotion/styled":"^11.0.0","@mui/icons-material":"^9.0.0","@mui/material":"^9.0.0","i18next":"^24.0.0 || ^26.0.0","react":"^19.0.0","react-dom":"^19.0.0","react-i18next":"^15.0.0 || ^17.0.0","react-router-dom":"^6.0.0 || ^7.0.0"},"overrides":{"tsup":{"esbuild":"^0.28.1"},"react-router":"^8.3.0"},"devDependencies":{"@emotion/react":"^11.14.0","@emotion/styled":"^11.14.1","@mui/icons-material":"^9.2.0","@mui/material":"^9.0.1","@commitlint/cli":"^21.2.1","@commitlint/config-conventional":"^21.2.0","@testing-library/dom":"^10.4.1","@testing-library/jest-dom":"^7.0.0","@testing-library/react":"^16.3.2","@testing-library/user-event":"^14.6.1","@types/node":"^26.1.2","@types/react":"^19.2.18","@types/react-dom":"^19.2.4","@vitejs/plugin-react":"^6.0.5","@vitest/coverage-v8":"^4.1.7","happy-dom":"^20.11.1","i18next":"^26.3.6","react":"^19.2.8","react-dom":"^19.2.8","react-i18next":"^17.0.11","react-router-dom":"^7.18.1","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^4.1.7"},"_id":"@4cloudguru/cloud-suite-ui@0.13.1","bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","_integrity":"sha512-sGdsr32ihb6bAzYf4VO4V+o1Wz9GRkfQNL16pqWbKenu8iiD/Ur/kyMyxwz82GdFDnF5ktSCuqaK0mlpeygcBA==","_resolved":"/home/runner/work/cloud-suite-ui/cloud-suite-ui/4cloudguru-cloud-suite-ui-0.13.1.tgz","_from":"file:4cloudguru-cloud-suite-ui-0.13.1.tgz","_nodeVersion":"24.20.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-sGdsr32ihb6bAzYf4VO4V+o1Wz9GRkfQNL16pqWbKenu8iiD/Ur/kyMyxwz82GdFDnF5ktSCuqaK0mlpeygcBA==","shasum":"a2d6a2c8db987eb4682a13fb035ff47c6ac45914","tarball":"https://registry.npmjs.org/@4cloudguru/cloud-suite-ui/-/cloud-suite-ui-0.13.1.tgz","fileCount":7,"unpackedSize":198096,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@4cloudguru%2fcloud-suite-ui@0.13.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDm/QXROs6K4Xg3hCgGnjngrB8v4MoIa+0IuL+6efILpAiBbMYYrLsA7ZEONlic8RB/c6YOk77F7t53PfbYHVlhYkw=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3b1f451a-0a05-4b8b-9618-01e95d5b1f7c"}},"directories":{},"maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cloud-suite-ui_0.13.1_1788957984141_0.8787279769121474"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-12T04:44:25.358Z","modified":"2026-09-09T12:46:24.618Z","0.9.0":"2026-08-12T04:44:25.718Z","0.9.1":"2026-08-12T21:32:34.502Z","0.9.2":"2026-08-21T01:31:27.947Z","0.10.0":"2026-08-21T18:26:22.906Z","0.11.0":"2026-08-28T16:29:43.812Z","0.11.1":"2026-08-30T08:15:24.574Z","0.12.0":"2026-08-30T18:08:47.703Z","0.13.0":"2026-08-31T16:03:45.833Z","0.13.1":"2026-09-09T12:46:24.274Z"},"bugs":{"url":"https://github.com/4cloudguru/cloud-suite-ui/issues"},"license":"Apache-2.0","homepage":"https://github.com/4cloudguru/cloud-suite-ui#readme","repository":{"type":"git","url":"git+https://github.com/4cloudguru/cloud-suite-ui.git"},"description":"Shared UI foundation (theme, identity, app shell, and cross-cutting components) for the Terraform suite frontends.","maintainers":[{"name":"dragonthegn","email":"stbacon@gmail.com"}],"readme":"# @4cloudguru/cloud-suite-ui\n\nShared UI foundation for the Terraform suite frontends\n([terraform-registry-frontend](https://github.com/sethbacon/terraform-registry-frontend)\nand [terraform-state-manager-frontend](https://github.com/sethbacon/terraform-state-manager-frontend)).\nIt centralises the look-and-feel and cross-cutting behaviour so both apps stay in\nvisual and behavioural parity from a single source of truth.\n\n## What's inside\n\n| Area           | Exports                                                                                                                                                               |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Tokens**     | `BRAND_PRIMARY`, `SECONDARY_LIGHT`, `SECONDARY_DARK`, dark surfaces, font stack, `BORDER_RADIUS`, `RTL_LANGUAGES`                                                     |\n| **Theme**      | `createAppTheme(mode, prefersReducedMotion, direction, overrides)`, `SuiteThemeProvider`, `useThemeMode`                                                              |\n| **Identity**   | `AuthProvider` (parameterised by an `AuthApi`), `useAuth` (returns `hasScope`, `memberships`, `organizationChoices`, `currentOrganizationId`, `setCurrentOrganization`), `ADMIN_SCOPE`, `SESSION_WARNING_LEAD_MS`, `SessionExpiryWarning`, `ORGANIZATION_HEADER`, `DEFAULT_ORGANIZATION_KEY`, `resolveCurrentOrganization`, `shouldOfferOrganizationChoice`, `actingOrganizationChoices`, types |\n| **Consent**    | `ConsentProvider`, `useConsent`, `ConsentBanner`                                                                                                                      |\n| **Components** | `PageHeader`, `DashboardCard`, `Page`, `NotificationChannelsSection`, `ApiKeyExpirySettingsCard`, `BrandingSettingsCard` (requires a host-supplied `validators` prop) |\n| **Shell**      | `SuiteLayout` (parameterised by nav + branding + auth), `SuiteSwitcher`, `OrganizationPicker`, nav types                                                              |\n| **Utils**      | `isSafeUrl` (host-supplied URL guard for navigation / image sinks)                                                                                                    |\n\n### Acting organization\n\nA user who belongs to more than one organization has to say which one a **write** belongs to.\n`AuthProvider` resolves that from their memberships plus a remembered choice, and exposes it as\n`currentOrganizationId`; `OrganizationPicker` renders the choice when there is one.\n\nThree properties are worth knowing before wiring it:\n\n- **A single-organization deployment is unchanged.** With one membership the selection is implied,\n  `OrganizationPicker` renders nothing, and no header has to be sent for writes to work.\n- **The remembered choice is a hint, never an authority.** It selects a membership only when it\n  matches one the server just returned, so a hand-edited value — or one left behind by a different\n  user of the same browser — is discarded rather than honoured. The key is also cleared on sign-out.\n- **Switching re-resolves the session.** `allowed_scopes` is the effective set for the *selected*\n  organization, so `setCurrentOrganization` performs the fresh `getCurrentUser()` that\n  `MeResponse.allowed_scopes` tells hosts they must, rather than leaving stale scopes in place.\n- **A platform administrator is not a member of anything.** They reach every organization and\n  belong to none, so their memberships are the wrong universe to derive a choice from: the server\n  insists such a caller names one, and a membership-driven picker offers them nothing to name.\n  Pass the organizations they may act in as `selectableOrganizations` and the picker offers those;\n  `organizationChoices` is the resulting union and is what `OrganizationPicker` renders and what\n  `setCurrentOrganization` validates against. Omit the prop and every existing behaviour is\n  unchanged, because the union is then the memberships themselves. It is a display universe, not\n  a grant — the server still refuses any organization the caller may not reach.\n\nSend the selection on every request as `ORGANIZATION_HEADER` (`X-Organization-Id`). The same name\nis defined server-side in `terraform-suite-identity`'s `identity/tenantscope`. It is a **claim**:\nthe server verifies it against a scope it resolved itself and refuses anything the caller may not\nreach, so this is not an authorization boundary.\n\nFramework packages (React, MUI, Emotion, i18next, react-router) are\n**peer dependencies** — the consuming app provides a single copy at runtime.\n\n## Develop\n\nRequires Node `>=22.0.0 <25` (see `engines` in `package.json`).\n\n```bash\nnpm install\nnpm run typecheck   # tsc --noEmit\nnpm test            # vitest\nnpm run build       # tsup -> dist/ (ESM + .d.ts)\n```\n\n## Publishing (GitHub Packages)\n\nPublishing is automated by [`.github/workflows/publish.yml`](.github/workflows/publish.yml):\ncreate a GitHub Release tagged `vX.Y.Z` (matching `package.json`) and the workflow\nbuilds, type-checks, tests, and runs `npm publish` to `https://npm.pkg.github.com`\nusing the repo's `GITHUB_TOKEN`.\n\n**Integrity guarantees for consumers:**\n\n- The publish job refuses to publish unless the triggering ref is exactly the git tag matching\n  `package.json`'s version — a manual `workflow_dispatch` run against an arbitrary branch is\n  rejected, not just discouraged. This tag/version check is the guarantee enforced by code in\n  this repository. The job also targets a GitHub Environment (`release`); any human-review gate\n  on that environment must be configured as a required-reviewer rule in repo **Settings** (not\n  tracked in git), so independent-review protection is not guaranteed by this repository alone.\n- Before `npm publish`, CI asserts the tarball (`npm pack --dry-run`) only contains `dist/` plus\n  `package.json`/`README.md`/`LICENSE`/`NOTICE` — no source, tests, or config files ship.\n- Every release generates [GitHub Artifact Attestations](https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations)\n  — build provenance plus a CycloneDX SBOM — bound to the exact published npm tarball. Verify by\n  fetching the tarball and checking it:\n\n  ```bash\n  npm pack @4cloudguru/cloud-suite-ui\n  gh attestation verify --repo 4cloudguru/cloud-suite-ui ./4cloudguru-cloud-suite-ui-*.tgz\n  ```\n\n  Releases also carry [npm provenance](https://docs.npmjs.com/generating-provenance-statements),\n  verifiable without the `gh` CLI:\n\n  ```bash\n  npm audit signatures\n  ```\n\n- CI runs `npm audit --audit-level=moderate` on every push/PR, and CodeQL (`javascript-typescript`)\n  runs on every push/PR plus a weekly schedule (see [`.github/workflows/codeql.yml`](.github/workflows/codeql.yml)).\n- A [`commitlint`](https://commitlint.js.org/) check on every PR enforces Conventional Commits,\n  since [release-please](.github/workflows/release-please.yml) derives version bumps solely from\n  commit messages.\n\nSee [SECURITY.md](SECURITY.md) for the vulnerability disclosure policy.\n\n## Consuming (in each frontend)\n\nThe package is public on the npm registry, so no `.npmrc` or auth token is needed:\n\n```bash\nnpm install @4cloudguru/cloud-suite-ui\n```\n\n```tsx\nimport { SuiteThemeProvider, PageHeader, useAuth } from '@4cloudguru/cloud-suite-ui'\n```\n\n> This package is a **build-time** dependency only; each app remains independently\n> deployable. Wiring the two apps to consume it is intentionally a separate step.\n\n> This package is **ESM-only** (`\"type\": \"module\"`, a single `import` export condition, no\n> `require`) — consume it from an ESM build/toolchain. It also declares `engines.node`\n> (`>=22.0.0 <25`); installing under an older/newer Node major is unsupported.\n\n## Internationalization (i18n)\n\nEvery component resolves user-facing copy through `useTranslation()`'s `t(key, { defaultValue })`,\nso a host app's i18next configuration owns translation and an incomplete bundle still renders\nreadable English.\n\n`BrandingSettingsCard` layers a **host-supplied `strings` prop** on top of that same contract, for\napps that already have translated copy for their own field labels/help text and would rather pass\nit straight through than duplicate it into an i18next bundle. Precedence per field is\n`strings.fields[key]?.label ?? t('branding.fields.<key>.label', { defaultValue: '<English label>' })`\n(and the same for `helperText`) — an app that supplies no `strings` entry for a field still gets a\ntranslatable label/helper text via `t()`; supplying an entry with e.g. `errorText` but no\n`helperText` intentionally renders no helper at all (the host is presumed to own that field's copy\noutright), rather than falling back to the `t()`-resolved English.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the prop-contract stability convention that applies to\n`BrandingSettingsCard`, `NotificationChannelsSection`, `ApiKeyExpirySettingsCard`, and\n`UIThemeConfig` specifically — a separate concern from this section's translation contract, which\napplies uniformly to every component.\n\n## Security model\n\n- **Token custody is the host app's responsibility.** `AuthProvider` is parameterised by an\n  `AuthApi` your app implements (`getCurrentUser`/`login`/`logout`/`refreshToken`/etc.) — this\n  library never reads or writes a token/cookie itself. Prefer an HttpOnly cookie over storing a\n  bearer token in `localStorage`/`sessionStorage` if your backend supports it.\n- **`onClearStorage` is how you clear YOUR app's cached auth data when the session ends** — on\n  explicit logout AND when the session fails closed (a 401, a lapsed session, or a malformed\n  `/me` response). Pass it whenever your app caches anything auth-related (a bearer token, query\n  data keyed to the signed-in user) outside of `AuthProvider`'s own React state. One deliberate\n  carve-out: a `/me` that returns 200 with a `session_expires_at` **already in the past** is read\n  as a disagreement between the client and server clocks, not as an expiry — no expiry is\n  scheduled, `onClearStorage` does not fire, and a `console.warn` names the skew. Otherwise a\n  browser clock running ahead of the server would lock the user out on every `/me` (#178).\n- **`hasScope`/`allowedScopes` are UI-visibility gates only — NOT an authorization boundary.**\n  They hide/show nav items and affordances client-side; every backend endpoint must\n  independently re-enforce authorization on every request regardless of what the client believes.\n  The special `ADMIN_SCOPE` (`'admin'`) wildcard mirrors the backend's own admin-wildcard\n  convention — do not rely on it as a security control in this library.\n- **`refreshSession()` logs out on failure** (a failed token refresh clears the session rather\n  than leaving a stale/ambiguous state); `authError` on the auth context is a sanitized,\n  display-safe string describing the most recent failed session-resolution call — never the raw\n  error object, response body, headers, or URLs — if your app wants to distinguish a network blip\n  from a real \"not logged in\" state.\n- Pass an app-specific `storageKey` to `ConsentProvider`/`SuiteThemeProvider`, and an app-specific\n  `groupStateStorageKey` to `SuiteLayout`, if your app shares an origin with a sibling suite app —\n  the default keys are generic and will collide otherwise (all three log a one-time console\n  warning if you don't). `SuiteLayout` clears its own persisted nav-group state on every\n  transition to unauthenticated; consent preferences deliberately survive, since a consent\n  decision is origin-scoped rather than session-scoped.\n- **`isSafeUrl` is the URL guard the shared components apply to host-supplied URLs** before using\n  them for navigation (`SuiteSwitcher`) or image sinks (`SuiteLayout`/`SuiteThemeProvider`\n  branding). It is exported so your app can apply the same allowlist (http/https/mailto/tel and\n  relative paths only) to any backend- or user-influenced URL at its own boundary. Compose rather\n  than re-derive it — an app that needs a narrower rule should call `isSafeUrl` first and layer its\n  own check on top, so a future fix to the shared parsing logic reaches every consumer:\n\n  ```ts\n  export function isSafeExternalUrl(value: string | null | undefined): value is string {\n    if (!isSafeUrl(value)) return false // shared base allowlist + normalisation\n    if (/^[/#.]/.test(value.trim())) return true // relative — already screened above\n    return new URL(value.trim()).protocol === 'https:' // app-specific narrowing\n  }\n  ```\n\n- Route props (`SuiteLayout`'s `NavItem.path` and `loginPath`, `DashboardCard`'s `to`) must be\n  in-app paths beginning with `/`. Anything absolute or protocol-relative is rejected with a\n  console warning and falls back to `/`.\n","readmeFilename":"README.md"}