{"_id":"@accurix/centrinfo-analytics","_rev":"5-3d8da643766aefebe1a289f29b574c08","name":"@accurix/centrinfo-analytics","dist-tags":{"latest":"3.0.0"},"versions":{"0.1.1":{"name":"@accurix/centrinfo-analytics","version":"0.1.1","keywords":["centrinfo","analytics","liveboard","embed","sdk"],"license":"SEE LICENSE IN LICENSE.md","_id":"@accurix/centrinfo-analytics@0.1.1","maintainers":[{"name":"accurix","email":"accurixtech@gmail.com"}],"homepage":"https://github.com/accurix-tech/accurix-web#readme","bugs":{"url":"https://github.com/accurix-tech/accurix-web/issues"},"dist":{"shasum":"c22dff0cdfed21c5d850963b642eae9804f64035","tarball":"https://registry.npmjs.org/@accurix/centrinfo-analytics/-/centrinfo-analytics-0.1.1.tgz","fileCount":23,"integrity":"sha512-XZy/OwR6gwqB7nW1ZBv2gUZZhhbjuxXUDGdZDKszE9mA22HQI2ngMRfQkwFs5Y+/okOj7423uajIA5Acj6PllA==","signatures":[{"sig":"MEQCIBYuMPwJdvrqMYV8C4V/PNGpAZwNVQS4pVAZ+6cJo6uVAiBK9eBhaUkHpfxw0Z9ov/vJWOT4skLaqfmdZVC2Kvd1Cg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":246409},"main":"./dist/index.cjs","type":"module","_from":"file:accurix-centrinfo-analytics-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.cjs"},"./package.json":"./package.json","./web-components":{"types":"./dist/web-components.d.ts","import":"./dist/web-components.mjs","require":"./dist/web-components.cjs"}},"private":false,"scripts":{"dev":"vite --config vite.demo.config.ts --host 0.0.0.0","lint":"eslint .","build":"tsdown --config tsdown.config.ts","preview":"vite preview --config vite.demo.config.ts --host 0.0.0.0","release":"pnpm verify:release && pnpm publish:npm","test-e2e":"playwright test","build-app":"pnpm build","test-unit":"vitest run","build:demo":"vite build --config vite.demo.config.ts","lint-write":"eslint . --fix","check-types":"tsc --noEmit","publish:npm":"npm publish --access public","pack:dry-run":"npm --cache /tmp/accurix-npm-cache pack --dry-run","verify:release":"pnpm check-types && pnpm lint && pnpm test-unit && pnpm build && pnpm build:demo && pnpm pack:dry-run"},"_npmUser":{"name":"accurix","email":"accurixtech@gmail.com"},"_resolved":"/tmp/96eae54f8fc64b7fa295d13d3d8d49ec/accurix-centrinfo-analytics-0.1.1.tgz","_integrity":"sha512-XZy/OwR6gwqB7nW1ZBv2gUZZhhbjuxXUDGdZDKszE9mA22HQI2ngMRfQkwFs5Y+/okOj7423uajIA5Acj6PllA==","repository":{"url":"git+https://github.com/accurix-tech/accurix-web.git","type":"git","directory":"sdk/centrinfo-analytics"},"_npmVersion":"11.6.2","description":"Secure, framework-agnostic SDK for embedding Centrinfo Answers and Liveboards.","directories":{},"sideEffects":["./dist/web-components.mjs","./dist/web-components.cjs"],"_nodeVersion":"24.12.0","dependencies":{"echarts":"^5.6.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.0.0","jsdom":"^26.0.0","react":"19.1.0","eslint":"^9.27.0","tsdown":"^0.18.0","vitest":"^3.2.0","typescript":"^5.8.0","@types/react":"^19.0.0","@playwright/test":"^1.50.0","@accurix/centrinfo-results":"^0.1.0","@accurix/web-config-eslint":"^0.0.0"},"peerDependencies":{"react":"19.1.0","@accurix/centrinfo":"^0.1.1"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/centrinfo-analytics_0.1.1_1784679668856_0.22220641735309998","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@accurix/centrinfo-analytics","version":"0.1.2","keywords":["centrinfo","analytics","liveboard","embed","sdk"],"license":"SEE LICENSE IN LICENSE.md","_id":"@accurix/centrinfo-analytics@0.1.2","maintainers":[{"name":"accurix","email":"accurixtech@gmail.com"}],"homepage":"https://github.com/accurix-tech/accurix-web#readme","bugs":{"url":"https://github.com/accurix-tech/accurix-web/issues"},"dist":{"shasum":"4979f37c1e472961b57e8e4d56e20c663a244d08","tarball":"https://registry.npmjs.org/@accurix/centrinfo-analytics/-/centrinfo-analytics-0.1.2.tgz","fileCount":21,"integrity":"sha512-NXpflX0XBB36mJgaz06eD0aO4ti7hTxocFcOTn1gq1JwoVHb2t3clQXJUqVpQ5sK52n3Wig4hCSrgxvCi/lhAQ==","signatures":[{"sig":"MEYCIQDAJKv/00eOTbfPl2n/CLdpbUNk3s2A8HERGmcs0MYazAIhAKQBxD+rNqyNjCDIy3MlaYR9kKCMsglSCKAg8Ecwc5Ql","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":326930},"main":"./dist/index.cjs","type":"module","_from":"file:accurix-centrinfo-analytics-0.1.2.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.mts","import":"./dist/react.mjs","require":"./dist/react.cjs"},"./package.json":"./package.json","./web-components":{"types":"./dist/web-components.d.mts","import":"./dist/web-components.mjs","require":"./dist/web-components.cjs"}},"private":false,"scripts":{"dev":"vite --config vite.demo.config.ts --host 0.0.0.0","lint":"eslint .","build":"tsdown --config tsdown.config.ts","preview":"vite preview --config vite.demo.config.ts --host 0.0.0.0","release":"pnpm verify:release && pnpm publish:npm","test-e2e":"playwright test","build-app":"pnpm build","test-unit":"vitest run","build:demo":"vite build --config vite.demo.config.ts","lint-write":"eslint . --fix","check-types":"tsc --noEmit","publish:npm":"npm publish --access public","pack:dry-run":"npm --cache /tmp/accurix-npm-cache pack --dry-run","verify:release":"pnpm check-types && pnpm lint && pnpm test-unit && pnpm build && pnpm build:demo && pnpm pack:dry-run"},"_npmUser":{"name":"accurix","email":"accurixtech@gmail.com"},"_resolved":"/tmp/eff9753372924159f5ce92065eb23f76/accurix-centrinfo-analytics-0.1.2.tgz","_integrity":"sha512-NXpflX0XBB36mJgaz06eD0aO4ti7hTxocFcOTn1gq1JwoVHb2t3clQXJUqVpQ5sK52n3Wig4hCSrgxvCi/lhAQ==","repository":{"url":"git+https://github.com/accurix-tech/accurix-web.git","type":"git","directory":"sdk/centrinfo-analytics"},"_npmVersion":"11.6.2","description":"Secure, framework-agnostic SDK for embedding Centrinfo Answers and Liveboards.","directories":{},"sideEffects":["./dist/web-components.mjs","./dist/web-components.cjs"],"_nodeVersion":"24.12.0","dependencies":{"echarts":"^5.6.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.0.0","jsdom":"^26.0.0","react":"19.1.0","eslint":"^9.27.0","tsdown":"^0.18.0","vitest":"^3.2.0","typescript":"^5.8.0","@types/react":"^19.0.0","@playwright/test":"^1.50.0","@accurix/centrinfo-results":"^0.1.0","@accurix/web-config-eslint":"^0.0.0"},"peerDependencies":{"react":"19.1.0","@accurix/centrinfo":"^0.1.2"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/centrinfo-analytics_0.1.2_1786234692940_0.40568678149198933","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@accurix/centrinfo-analytics","version":"0.1.3","keywords":["centrinfo","analytics","liveboard","embed","sdk"],"license":"SEE LICENSE IN LICENSE.md","_id":"@accurix/centrinfo-analytics@0.1.3","maintainers":[{"name":"accurix","email":"accurixtech@gmail.com"}],"homepage":"https://github.com/accurix-tech/accurix-web#readme","bugs":{"url":"https://github.com/accurix-tech/accurix-web/issues"},"dist":{"shasum":"75e9b8b3b1ae41a041687d6bfea3ca549536fd73","tarball":"https://registry.npmjs.org/@accurix/centrinfo-analytics/-/centrinfo-analytics-0.1.3.tgz","fileCount":21,"integrity":"sha512-reGI4pYjpDwAXd8E5PfvwWNMnrfPaq6Pfik2as+ixMaadAPsRbrRGtecA3B+Bt45XU2iaoa/fryr1E0aCk7SGA==","signatures":[{"sig":"MEYCIQDc/1NJY9QIrNl3IQPEAoe7O9XHCqLSHOSO/wfbA1XG4AIhANnQ7+StOH2oyTcp5fTQYjETR5gSmGsvnvC93GzduF5h","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":345884},"main":"./dist/index.cjs","type":"module","_from":"file:accurix-centrinfo-analytics-0.1.3.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.mts","import":"./dist/react.mjs","require":"./dist/react.cjs"},"./package.json":"./package.json","./web-components":{"types":"./dist/web-components.d.mts","import":"./dist/web-components.mjs","require":"./dist/web-components.cjs"}},"private":false,"scripts":{"dev":"vite --config vite.demo.config.ts --host 0.0.0.0","lint":"eslint .","build":"tsdown --config tsdown.config.ts","preview":"vite preview --config vite.demo.config.ts --host 0.0.0.0","release":"pnpm verify:release && pnpm publish:npm","test-e2e":"playwright test","build-app":"pnpm build","test-unit":"vitest run","build:demo":"vite build --config vite.demo.config.ts","lint-write":"eslint . --fix","check-types":"tsc --noEmit","publish:npm":"npm publish --access public","pack:dry-run":"npm --cache /tmp/accurix-npm-cache pack --dry-run","verify:release":"pnpm check-types && pnpm lint && pnpm test-unit && pnpm build && pnpm build:demo && pnpm pack:dry-run"},"_npmUser":{"name":"accurix","email":"accurixtech@gmail.com"},"_resolved":"/tmp/e2ab2c7318cf44229f337399560ff3a6/accurix-centrinfo-analytics-0.1.3.tgz","_integrity":"sha512-reGI4pYjpDwAXd8E5PfvwWNMnrfPaq6Pfik2as+ixMaadAPsRbrRGtecA3B+Bt45XU2iaoa/fryr1E0aCk7SGA==","repository":{"url":"git+https://github.com/accurix-tech/accurix-web.git","type":"git","directory":"sdk/centrinfo-analytics"},"_npmVersion":"11.6.2","description":"Secure, framework-agnostic SDK for embedding Centrinfo Answers and Liveboards.","directories":{},"sideEffects":["./dist/web-components.mjs","./dist/web-components.cjs"],"_nodeVersion":"24.12.0","dependencies":{"echarts":"^5.6.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.0.0","jsdom":"^26.0.0","react":"19.1.0","eslint":"^9.27.0","tsdown":"^0.18.0","vitest":"^3.2.0","typescript":"^5.8.0","@types/react":"^19.0.0","@playwright/test":"^1.50.0","@accurix/centrinfo-results":"^0.1.0","@accurix/web-config-eslint":"^0.0.0"},"peerDependencies":{"react":"19.1.0","@accurix/centrinfo":"^0.1.3"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/centrinfo-analytics_0.1.3_1787265952221_0.2948090564037642","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@accurix/centrinfo-analytics","version":"1.0.0","keywords":["centrinfo","analytics","liveboard","embed","sdk"],"license":"SEE LICENSE IN LICENSE.md","_id":"@accurix/centrinfo-analytics@1.0.0","maintainers":[{"name":"accurix","email":"accurixtech@gmail.com"}],"homepage":"https://github.com/accurix-tech/accurix-web#readme","bugs":{"url":"https://github.com/accurix-tech/accurix-web/issues"},"dist":{"shasum":"8ad647aaf6304af6368f8c204b2c7a38f3868c2d","tarball":"https://registry.npmjs.org/@accurix/centrinfo-analytics/-/centrinfo-analytics-1.0.0.tgz","fileCount":21,"integrity":"sha512-+JlGa0hAqgPQDeyXF5bjmoO75180nL7kHcsjIqvYS3eEQEs0TKhCN/W6h/hqpXufG0rNBHYzXyfyjeZ3+ZwwvQ==","signatures":[{"sig":"MEYCIQDsG7StI24kus/8NUZTY20q+WTp/LgJ9lH2m20AF/pvDAIhALZ5xmRSuEZABB1W1ro8NVUIc9OTJcPkFzCwKiQLYl2M","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":666417},"main":"./dist/index.cjs","type":"module","_from":"file:accurix-centrinfo-analytics-1.0.0.tgz","types":"./dist/index.d.mts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.mts","import":"./dist/react.mjs","require":"./dist/react.cjs"},"./package.json":"./package.json","./web-components":{"types":"./dist/web-components.d.mts","import":"./dist/web-components.mjs","require":"./dist/web-components.cjs"}},"private":false,"scripts":{"dev":"vite --config vite.demo.config.ts --host 0.0.0.0","lint":"eslint .","build":"tsdown --config tsdown.config.ts","preview":"vite preview --config vite.demo.config.ts --host 0.0.0.0","release":"pnpm verify:release && pnpm publish:npm","test-e2e":"playwright test","build-app":"pnpm build","test-unit":"vitest run","build:demo":"vite build --config vite.demo.config.ts","lint-write":"eslint . --fix","check-types":"tsc --noEmit","publish:npm":"npm publish --access public","pack:dry-run":"npm --cache /tmp/accurix-npm-cache pack --dry-run","verify:release":"pnpm check-types && pnpm lint && pnpm test-unit && pnpm build && pnpm build:demo && pnpm pack:dry-run"},"_npmUser":{"name":"accurix","email":"accurixtech@gmail.com"},"_resolved":"/tmp/006f33541c4a0919a0723436c7fcd251/accurix-centrinfo-analytics-1.0.0.tgz","_integrity":"sha512-+JlGa0hAqgPQDeyXF5bjmoO75180nL7kHcsjIqvYS3eEQEs0TKhCN/W6h/hqpXufG0rNBHYzXyfyjeZ3+ZwwvQ==","repository":{"url":"git+https://github.com/accurix-tech/accurix-web.git","type":"git","directory":"sdk/centrinfo-analytics"},"_npmVersion":"11.6.2","description":"Secure, framework-agnostic SDK for embedding Centrinfo Answers and Liveboards.","directories":{},"sideEffects":["./dist/web-components.mjs","./dist/web-components.cjs"],"_nodeVersion":"24.12.0","dependencies":{"echarts":"^5.6.0","echarts-gl":"2.0.9"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.0.0","jsdom":"^26.0.0","react":"19.1.0","eslint":"^9.27.0","tsdown":"^0.18.0","vitest":"^3.2.0","typescript":"^5.8.0","@types/react":"^19.0.0","@playwright/test":"^1.50.0","@accurix/centrinfo-results":"^0.1.0","@accurix/web-config-eslint":"^0.0.0"},"peerDependencies":{"react":"19.1.0","@accurix/centrinfo":"^0.2.0"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/centrinfo-analytics_1.0.0_1788306180034_0.5414106535749894","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@accurix/centrinfo-analytics","version":"3.0.0","private":false,"type":"module","sideEffects":["./dist/web-components.mjs","./dist/web-components.cjs"],"main":"./dist/index.cjs","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.mts","import":"./dist/react.mjs","require":"./dist/react.cjs"},"./web-components":{"types":"./dist/web-components.d.mts","import":"./dist/web-components.mjs","require":"./dist/web-components.cjs"},"./package.json":"./package.json"},"description":"Secure, framework-agnostic SDK for embedding Centrinfo Answers and Liveboards.","keywords":["centrinfo","analytics","liveboard","embed","sdk"],"license":"SEE LICENSE IN LICENSE.md","repository":{"type":"git","url":"git+https://github.com/accurix-tech/accurix-web.git","directory":"sdk/centrinfo-analytics"},"dependencies":{"echarts":"^5.6.0","echarts-gl":"2.0.9"},"devDependencies":{"@playwright/test":"^1.50.0","@types/react":"^19.0.0","eslint":"^9.27.0","jsdom":"^26.0.0","react":"19.1.0","tsdown":"^0.18.0","typescript":"^5.8.0","vite":"^7.0.0","vitest":"^3.2.0","@accurix/centrinfo-results":"^0.1.0","@accurix/web-config-eslint":"^0.0.0"},"module":"./dist/index.mjs","peerDependencies":{"react":"19.1.0","@accurix/centrinfo":"^0.4.0"},"peerDependenciesMeta":{"react":{"optional":true}},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build":"tsdown --config tsdown.config.ts","build-app":"pnpm build","build:demo":"vite build --config vite.demo.config.ts","check-types":"tsc --noEmit","dev":"vite --config vite.demo.config.ts --host 0.0.0.0","lint":"eslint .","lint-write":"eslint . --fix","pack:dry-run":"npm --cache /tmp/accurix-npm-cache pack --dry-run","preview":"vite preview --config vite.demo.config.ts --host 0.0.0.0","publish:npm":"npm publish --access public","release":"pnpm verify:release && pnpm publish:npm","test-e2e":"playwright test","test-unit":"vitest run","verify:release":"pnpm check-types && pnpm lint && pnpm test-unit && pnpm build && pnpm build:demo && pnpm pack:dry-run"},"_id":"@accurix/centrinfo-analytics@3.0.0","bugs":{"url":"https://github.com/accurix-tech/accurix-web/issues"},"homepage":"https://github.com/accurix-tech/accurix-web#readme","_integrity":"sha512-3yBFF3gdt43RI0DR+nj+uYfbI1XHykCOHT2mbS/4rNkoZLNU9vGwe1lfV4GI8wRKhoMPNITlZX8fyVnMIBL1Wg==","_resolved":"/tmp/013b52138cce0cd0eef7b836ef54a74b/accurix-centrinfo-analytics-3.0.0.tgz","_from":"file:accurix-centrinfo-analytics-3.0.0.tgz","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-3yBFF3gdt43RI0DR+nj+uYfbI1XHykCOHT2mbS/4rNkoZLNU9vGwe1lfV4GI8wRKhoMPNITlZX8fyVnMIBL1Wg==","shasum":"6ddb372a5761370437b5fcceb93dab18eaffdcf2","tarball":"https://registry.npmjs.org/@accurix/centrinfo-analytics/-/centrinfo-analytics-3.0.0.tgz","fileCount":21,"unpackedSize":666417,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFld5bj0L7qQZnuNZWLNaysGTnvCGGU/6HhjWs5kPhxCAiEAsoRkSchoNhc41veNaPES9jN5AecD/EQ6AeQaL1N88dY="}]},"_npmUser":{"name":"accurix","email":"accurixtech@gmail.com"},"directories":{},"maintainers":[{"name":"accurix","email":"accurixtech@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/centrinfo-analytics_3.0.0_1788454543575_0.2911326891127559"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-22T00:21:08.655Z","modified":"2026-09-03T16:55:43.860Z","0.1.1":"2026-07-22T00:21:08.986Z","0.1.2":"2026-08-09T00:18:13.257Z","0.1.3":"2026-08-20T22:45:52.414Z","1.0.0":"2026-09-01T23:43:00.210Z","3.0.0":"2026-09-03T16:55:43.725Z"},"bugs":{"url":"https://github.com/accurix-tech/accurix-web/issues"},"license":"SEE LICENSE IN LICENSE.md","homepage":"https://github.com/accurix-tech/accurix-web#readme","keywords":["centrinfo","analytics","liveboard","embed","sdk"],"repository":{"type":"git","url":"git+https://github.com/accurix-tech/accurix-web.git","directory":"sdk/centrinfo-analytics"},"description":"Secure, framework-agnostic SDK for embedding Centrinfo Answers and Liveboards.","maintainers":[{"name":"accurix","email":"accurixtech@gmail.com"}],"readme":"# @accurix/centrinfo-analytics\n\nEmbed polished Centrinfo Liveboards and Answers in a customer application\nwithout exposing a Centrinfo user session, semantic-model details, SQL, or a\nsigning key to the browser.\n\nThis package is intentionally separate from `@accurix/centrinfo-widget`:\n\n- Use `@accurix/centrinfo-widget` for the floating or full-page conversational\n  chat experience.\n- Use `@accurix/centrinfo-analytics` for Liveboards and standalone Answers.\n- Both surfaces consume the same governed analytics result contract, so KPIs,\n  charts, explanations, filters, and customer permissions remain consistent.\n\n## What the embed includes\n\n- Responsive 12-column Liveboard layouts that stack cleanly on mobile.\n- Optional dashboard pages and nested tabs, rendered from the same published\n  Liveboard definition used inside Centrinfo.\n- KPI, line, multi-line, bar, pie, scatter, funnel, and table results.\n- Chart/table switching, chart sorting, always-visible chart zoom controls, card\n  expansion/minimization, fullscreen, and refresh.\n- Plain-language explanations that separate facts, possible drivers,\n  directional outlooks, and recommended next steps.\n- Approved filter presets, reporting periods, freshness, and safe row counts.\n- A built-in governed dashboard assistant for plain-language follow-up\n  questions and multi-answer comparisons, even when the public chat widget is\n  not installed.\n- Optional CSV/chart downloads plus polished whole-dashboard PDF and\n  PowerPoint exports.\n- Per-card failures, loading skeletons, auto-refresh, and accessible focus\n  states.\n- Shadow DOM isolation so a host site's CSS cannot break the Liveboard.\n\nThe public renderer deliberately does not display model names, query IDs,\ndataset names, SQL, or internal diagnostic metadata.\n\n## Ask Your Data response contract\n\n`askInsight` returns the same governed result used by Centrinfo Web. The SDK\ndoes not run a second analytics algorithm or ask the browser to infer meaning\nfrom raw rows. The response includes:\n\n- `analysisIntent`: the selected method, metric, breakdowns, comparison,\n  requested outputs/entities, and status.\n- `analysisCoverage`: whether every requested aspect has deterministic\n  evidence, plus any missing aspects.\n- `businessAnalysis`: calculated evidence, tables, charts, confidence,\n  quality, provenance, and the method-specific explanation.\n- `explanation`: the direct reader-facing answer, measured evidence, bounded\n  business meaning, unproven drivers, recommendations, forecast metadata,\n  limitations, and follow-up questions.\n- `chartRecommendation`: the backend-selected renderer-neutral chart contract.\n- `conversationId`: the thread identifier to reuse for follow-up questions.\n\nThe built-in mounts display this contract automatically. For a custom UI, use\nthe exported presentation helpers:\n\n```ts\nimport {\n  CentrinfoAnalyticsClient,\n  resolveAnalyticsExplanation,\n  resolveAnalyticsPresentationResult,\n  type AnalyticsQueryResult,\n} from '@accurix/centrinfo-analytics';\n\nconst result: AnalyticsQueryResult = await analytics.askInsight(answerId, {\n  question: 'Segment patients by utilization and describe each group.',\n  conversationId,\n});\n\n// Selects backend-provided derived artifacts for methods such as clustering,\n// regression, and association rules. It does not calculate new evidence.\nconst presentation = resolveAnalyticsPresentationResult(result);\nconst explanation = result.businessAnalysis?.explanation ?? resolveAnalyticsExplanation(result);\n\nrenderResult(presentation);\nrenderExplanation(explanation);\n```\n\nThe `@accurix/centrinfo/liveboards` entry re-exports the same result, intent,\ncoverage, business-analysis, and explanation types. `@accurix/centrinfo-results`\nis intentionally limited to chart/table/formatting primitives and does not own\nthe Ask transport or analytics logic.\n\n## Security model\n\nCreate an embed app in Centrinfo for each customer application. Centrinfo\nstores its public Ed25519 key and returns the private key once. Keep that\nprivate key in your backend or secret manager. Your backend signs a short-lived\nJWT for the signed-in customer; the browser only receives that token.\n\nTokens use `EdDSA`, audience `centrinfo-analytics`, the embed-app ID as issuer,\nand a lifetime of no more than 15 minutes. Include the organization ID, your\nstable external user ID, the allowed scopes, and only scalar external context\nvalues. Centrinfo also checks the browser Origin and the app's\nLiveboard/Answer allowlist on every request.\n\n## Browser usage\n\n```ts\nimport {\n  CentrinfoAnalyticsClient,\n  mountAnswer,\n  mountLiveboard,\n  mountLiveboardCollection,\n} from '@accurix/centrinfo-analytics';\n\nconst analytics = new CentrinfoAnalyticsClient({\n  apiBaseUrl: 'https://api.example.com',\n  embedAppId: 'YOUR_EMBED_APP_ID',\n  getAccessToken: async () => {\n    const response = await fetch('/api/centrinfo-embed-token');\n    const { token } = await response.json();\n    return token;\n  },\n});\n\nconst liveboard = mountLiveboard(analytics, '#sales-liveboard', {\n  liveboardId: 'PUBLISHED_LIVEBOARD_ID',\n  showTables: true,\n  showExplanations: true,\n  showDownload: false,\n  showAskAI: true,\n  allowTileExpand: true,\n});\n\n// Show every published Liveboard assigned to this SDK application.\n// This selector sits above each Liveboard's own pages and tabs.\nconst dashboards = mountLiveboardCollection(analytics, '#customer-dashboards', {\n  defaultLiveboardId: 'OPTIONAL_INITIAL_LIVEBOARD_ID',\n  navigation: 'tabs',\n  showTables: true,\n  showAskAI: true,\n});\n\nconst answer = mountAnswer(analytics, '#active-accounts', {\n  insightId: 'PUBLISHED_ANSWER_ID',\n  title: 'Active accounts',\n});\n\nanalytics.on('error', ({ error }) => console.error(error));\n\n// Later, if this view is removed:\nliveboard.destroy();\ndashboards.destroy();\nanswer.destroy();\n```\n\nEach client instance owns its token lifecycle and events, so multiple\norganizations or Liveboards can safely coexist on the same page.\n\n## Styling\n\nPass `theme` to `CentrinfoAnalyticsClient` when the embedded Liveboard should\nmatch the host application. The Liveboard renders in Shadow DOM, so prefer SDK\ntheme tokens instead of relying on global CSS overrides.\n\n```ts\nconst analytics = new CentrinfoAnalyticsClient({\n  apiBaseUrl: 'https://api.example.com',\n  embedAppId: 'YOUR_EMBED_APP_ID',\n  getAccessToken,\n  theme: {\n    accent: '#2563eb',\n    accentStrong: '#1d4ed8',\n    accentSoft: 'rgba(37, 99, 235, 0.1)',\n    background: '#f8fafc',\n    surface: '#ffffff',\n    surfaceMuted: '#f1f5f9',\n    text: '#101827',\n    mutedText: '#52647a',\n    subtleText: '#7a8da3',\n    border: '#dbe4ee',\n    radius: '16px',\n    fontFamily: 'Avenir Next, sans-serif',\n  },\n});\n```\n\n`mountLiveboardCollection` shows a tab or select control for every published\nLiveboard assigned to the SDK application. `defaultLiveboardId` only chooses\nthe first selected Liveboard. `navigationLabel` is optional; omit it when the\nhost application already labels the section.\n\n## Web component\n\nThe web-component entry auto-registers `<centrinfo-liveboard>` and\n`<centrinfo-answer>`. Pass the client through JavaScript; never place a signed\ntoken in an HTML attribute.\n\n```ts\nimport { CentrinfoAnalyticsClient } from '@accurix/centrinfo-analytics';\nimport '@accurix/centrinfo-analytics/web-components';\n\nconst client = new CentrinfoAnalyticsClient({\n  apiBaseUrl: 'https://api.example.com',\n  embedAppId: 'YOUR_EMBED_APP_ID',\n  getAccessToken: () =>\n    fetch('/api/centrinfo-embed-token').then(async (response) => {\n      const body = await response.json();\n      return body.token;\n    }),\n});\n\nconst liveboard = document.querySelector('centrinfo-liveboard');\nliveboard.configure(client, {\n  liveboardId: 'PUBLISHED_LIVEBOARD_ID',\n  showTables: false,\n  showDownload: false,\n});\n```\n\n```html\n<centrinfo-liveboard></centrinfo-liveboard>\n```\n\n## React\n\nReact is an optional peer dependency. The framework-neutral renderer remains\nthe source of truth; the React export is a small lifecycle wrapper around it.\n\n```tsx\nimport { CentrinfoLiveboard } from '@accurix/centrinfo-analytics/react';\n\nexport function CustomerDashboard() {\n  return (\n    <CentrinfoLiveboard\n      client={analytics}\n      liveboardId=\"PUBLISHED_LIVEBOARD_ID\"\n      showTables\n      showExplanations\n      allowTileExpand\n    />\n  );\n}\n```\n\n## Customer-facing controls\n\nVisibility remains an organization decision. Resolve the saved organization\npolicy on your server or in your authenticated host app and pass the approved\noptions to the mount:\n\n```ts\nmountLiveboard(analytics, '#customer-dashboard', {\n  liveboardId,\n  showTables: organizationPolicy.allowTables,\n  showDownload: organizationPolicy.allowDownloads,\n  showAskAI: organizationPolicy.allowQuestions,\n  showExplanations: organizationPolicy.allowExplanations,\n  maxTableRows: organizationPolicy.maxRows,\n});\n```\n\nThese UI controls do not replace backend enforcement. The embed app's resource\nallowlist, signed customer identity, role restrictions, field allowlists, row\nsecurity, and row limits remain authoritative.\n\n`showDownload` enables card and dashboard image exports, card CSV downloads,\nand board-level PDF / PowerPoint exports. Reports are generated server-side by\nrerunning every card with the same signed customer identity used by the\ndashboard; internal organization data is never substituted for the customer's\nscoped result.\n\n## Dashboard and card actions\n\nThe default customer viewer handles refresh, native share/copy-link, image\nexport, CSV download, PDF, PowerPoint, and Ask AI directly. It does not expose\nalert creation, question refinement, layout editing, copying, scheduling, or\ndeletion.\n\nPrivileged workflows are optional callbacks. Configure them only in a trusted\nhost that has already checked the signed-in user's permission:\n\n```ts\nmountLiveboard(analytics, '#customer-dashboard', {\n  liveboardId,\n  showDownload: true,\n  actions: {\n    createAlert: ({ tile, insight, result }) => {\n      permissions.require('analytics.alerts.create');\n      return alerts.open({ tileId: tile?.id, insightId: insight?.id, result });\n    },\n    refineQuestion: ({ insight }) => {\n      permissions.require('analytics.insights.create');\n      return questions.refine(insight?.id);\n    },\n    alertsAndDelivery: () => router.open('/analytics/alerts'),\n    analyzeDashboard: ({ liveboard }) => assistant.open(liveboard?.id),\n    editLayout: ({ liveboard }) => editor.open(liveboard?.id),\n    refreshSettings: ({ liveboard }) => refreshRules.open(liveboard?.id),\n    buildReportAndSchedule: ({ liveboard }) => schedules.open(liveboard?.id),\n    makeCopy: ({ liveboard }) => liveboards.copy(liveboard?.id),\n    deleteLiveboard: ({ liveboard }) => liveboards.confirmDelete(liveboard?.id),\n  },\n});\n```\n\nA callback-owned menu item is hidden when its handler is omitted. Supplying a\ncallback controls visibility but does not grant backend permission; the host\nand API must still authorize the operation.\n\n## Signing claims\n\nUse a server-side Ed25519 JWT library and sign claims shaped like:\n\n```json\n{\n  \"iss\": \"EMBED_APP_ID\",\n  \"aud\": \"centrinfo-analytics\",\n  \"sub\": \"YOUR_EXTERNAL_USER_ID\",\n  \"business_id\": \"optional-tenant-or-account-id\",\n  \"context\": {\n    \"region\": \"west\",\n    \"account_id\": \"acct_123\",\n    \"email\": \"signed-in-customer@example.com\"\n  },\n  \"iat\": 1784190000,\n  \"exp\": 1784190600\n}\n```\n\nNever put the private key, token, or sensitive context in HTML, query\nparameters, logs, or local storage.\n\n## Customer alerts\n\nAn organization can attach an alert rule to a Liveboard exposed by the embed\napp. A signed-in customer must explicitly opt in before Accurix evaluates or\nsends that alert for their data:\n\n```ts\nconst currentSubscription = await analytics.getAlertSubscription();\n\nif (!currentSubscription.enabled) {\n  await analytics.enableEmailAlerts();\n}\n\nawait analytics.disableAlerts();\n```\n\nThe token used for these calls must include `alerts:subscribe`. Put the\ncustomer's verified email and row-security keys in the server-signed `context`;\nthe SDK never accepts an email or identity value from browser input. Alert\nevaluation reuses that signed context. Customer delivery currently supports\nemail; Slack and Teams are reserved for linked organization-member identities.\n\n## Interactive demo\n\nThe demo uses realistic governed mock responses and never needs a real token:\n\n```bash\npnpm --filter @accurix/centrinfo-analytics dev\n```\n\nOpen `http://localhost:3006`. The demo includes approved filter presets,\nmulti-series charts, KPI explanations, a limited table, downloads, per-card\nrefresh, expansion, fullscreen, responsive layouts, and zoom controls.\n\n## Release\n\nRun the complete local package gate:\n\n```bash\npnpm --filter @accurix/centrinfo-analytics verify:release\npnpm --filter @accurix/centrinfo-analytics test-e2e\n```\n\nGitHub Actions publishes automatically when a tag matching\n`centrinfo-analytics-v<package-version>` is pushed. For version `0.1.0`:\n\n```bash\ngit tag centrinfo-analytics-v0.1.0\ngit push origin centrinfo-analytics-v0.1.0\n```\n\nThe workflow verifies that the tag equals `package.json`, runs type, lint,\nunit, build, package, and browser checks, then publishes with the existing\n`NPM_TOKEN` repository secret. It can also be run manually in dry-run mode.\n","readmeFilename":"README.md"}