@adminiumjs/adminium 0.1.0-rc.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.
- package/LICENSE +661 -0
- package/README.md +94 -0
- package/dashboard/assets/DeltaPill-dxlsGh-1.js +2 -0
- package/dashboard/assets/DeltaPill-dxlsGh-1.js.map +1 -0
- package/dashboard/assets/DistributionCorrelationWidgets-ztVy_W_R.js +2 -0
- package/dashboard/assets/DistributionCorrelationWidgets-ztVy_W_R.js.map +1 -0
- package/dashboard/assets/PartWholeWidgets-BDn0i0jt.js +2 -0
- package/dashboard/assets/PartWholeWidgets-BDn0i0jt.js.map +1 -0
- package/dashboard/assets/RemapEditor-z3vRY12e.js +2 -0
- package/dashboard/assets/RemapEditor-z3vRY12e.js.map +1 -0
- package/dashboard/assets/ReviewScreen-COkLQ3T7.js +2 -0
- package/dashboard/assets/ReviewScreen-COkLQ3T7.js.map +1 -0
- package/dashboard/assets/Sparkline-Cvwo368J.js +2 -0
- package/dashboard/assets/Sparkline-Cvwo368J.js.map +1 -0
- package/dashboard/assets/WidgetMissingCard-D0bPJKIs.js +2 -0
- package/dashboard/assets/WidgetMissingCard-D0bPJKIs.js.map +1 -0
- package/dashboard/assets/arc-CPxb74pf.js +2 -0
- package/dashboard/assets/arc-CPxb74pf.js.map +1 -0
- package/dashboard/assets/bars-ranking-components-9Asn_0gR.js +2 -0
- package/dashboard/assets/bars-ranking-components-9Asn_0gR.js.map +1 -0
- package/dashboard/assets/blocks-track-components-BST-NjK2.js +2 -0
- package/dashboard/assets/blocks-track-components-BST-NjK2.js.map +1 -0
- package/dashboard/assets/calendar-track-components-RgNtGtZR.js +2 -0
- package/dashboard/assets/calendar-track-components-RgNtGtZR.js.map +1 -0
- package/dashboard/assets/chrome-track-components-ClNsentC.js +2 -0
- package/dashboard/assets/chrome-track-components-ClNsentC.js.map +1 -0
- package/dashboard/assets/common-BY1j__bD.js +2 -0
- package/dashboard/assets/common-BY1j__bD.js.map +1 -0
- package/dashboard/assets/common-BdlXKpcB.js +2 -0
- package/dashboard/assets/common-BdlXKpcB.js.map +1 -0
- package/dashboard/assets/common-BqqhgMgB.js +2 -0
- package/dashboard/assets/common-BqqhgMgB.js.map +1 -0
- package/dashboard/assets/common-BribWmIo.js +2 -0
- package/dashboard/assets/common-BribWmIo.js.map +1 -0
- package/dashboard/assets/common-Cmf0_lKV.js +2 -0
- package/dashboard/assets/common-Cmf0_lKV.js.map +1 -0
- package/dashboard/assets/common-i0r48qY9.js +2 -0
- package/dashboard/assets/common-i0r48qY9.js.map +1 -0
- package/dashboard/assets/common-x8cfkwpc.js +2 -0
- package/dashboard/assets/common-x8cfkwpc.js.map +1 -0
- package/dashboard/assets/communication-track-components-CNLZXOH_.js +2 -0
- package/dashboard/assets/communication-track-components-CNLZXOH_.js.map +1 -0
- package/dashboard/assets/components-Bp5cFm2d.js +2 -0
- package/dashboard/assets/components-Bp5cFm2d.js.map +1 -0
- package/dashboard/assets/components-C4-O3_gD.js +2 -0
- package/dashboard/assets/components-C4-O3_gD.js.map +1 -0
- package/dashboard/assets/domain-ops-track-components-BPa41AU7.js +2 -0
- package/dashboard/assets/domain-ops-track-components-BPa41AU7.js.map +1 -0
- package/dashboard/assets/domain-track-components-CQ1i1X1t.js +2 -0
- package/dashboard/assets/domain-track-components-CQ1i1X1t.js.map +1 -0
- package/dashboard/assets/errors-BHUWiAQ3.js +2 -0
- package/dashboard/assets/errors-BHUWiAQ3.js.map +1 -0
- package/dashboard/assets/errors-BbyKweDG.js +2 -0
- package/dashboard/assets/errors-BbyKweDG.js.map +1 -0
- package/dashboard/assets/errors-CMQ6JC31.js +2 -0
- package/dashboard/assets/errors-CMQ6JC31.js.map +1 -0
- package/dashboard/assets/errors-D3nVgTmf.js +2 -0
- package/dashboard/assets/errors-D3nVgTmf.js.map +1 -0
- package/dashboard/assets/errors-IqJSoANC.js +2 -0
- package/dashboard/assets/errors-IqJSoANC.js.map +1 -0
- package/dashboard/assets/errors-gmIkO9F6.js +2 -0
- package/dashboard/assets/errors-gmIkO9F6.js.map +1 -0
- package/dashboard/assets/errors-vFk058Vh.js +2 -0
- package/dashboard/assets/errors-vFk058Vh.js.map +1 -0
- package/dashboard/assets/feeds-track-f-components-Cl_8SkGs.js +2 -0
- package/dashboard/assets/feeds-track-f-components-Cl_8SkGs.js.map +1 -0
- package/dashboard/assets/format-Lx4cQ8k-.js +2 -0
- package/dashboard/assets/format-Lx4cQ8k-.js.map +1 -0
- package/dashboard/assets/forms-track-components-Bc2Hoxdh.js +2 -0
- package/dashboard/assets/forms-track-components-Bc2Hoxdh.js.map +1 -0
- package/dashboard/assets/generated-1EfWhCMA.js +2 -0
- package/dashboard/assets/generated-1EfWhCMA.js.map +1 -0
- package/dashboard/assets/generated-BB3ZMxvx.js +2 -0
- package/dashboard/assets/generated-BB3ZMxvx.js.map +1 -0
- package/dashboard/assets/generated-C0JVNBRX.js +2 -0
- package/dashboard/assets/generated-C0JVNBRX.js.map +1 -0
- package/dashboard/assets/generated-C1W48_-3.js +2 -0
- package/dashboard/assets/generated-C1W48_-3.js.map +1 -0
- package/dashboard/assets/generated-CluiB_xY.js +2 -0
- package/dashboard/assets/generated-CluiB_xY.js.map +1 -0
- package/dashboard/assets/generated-DDGtlf-4.js +2 -0
- package/dashboard/assets/generated-DDGtlf-4.js.map +1 -0
- package/dashboard/assets/generated-DPCHvNto.js +2 -0
- package/dashboard/assets/generated-DPCHvNto.js.map +1 -0
- package/dashboard/assets/geo-track-components-Ct4-MSRw.js +3 -0
- package/dashboard/assets/geo-track-components-Ct4-MSRw.js.map +1 -0
- package/dashboard/assets/ibm-plex-sans-arabic-arabic-400-normal-CyU-ddYS.woff2 +0 -0
- package/dashboard/assets/ibm-plex-sans-arabic-arabic-500-normal-C4MQITzh.woff2 +0 -0
- package/dashboard/assets/ibm-plex-sans-arabic-arabic-600-normal-0pRdybE_.woff2 +0 -0
- package/dashboard/assets/ibm-plex-sans-arabic-arabic-700-normal-DrtBj6UE.woff2 +0 -0
- package/dashboard/assets/index-DPi4cduu.css +1 -0
- package/dashboard/assets/index-PB1II0WV.js +137 -0
- package/dashboard/assets/index-PB1II0WV.js.map +1 -0
- package/dashboard/assets/jetbrains-mono-latin-ext-wght-italic-BrDczivE.woff2 +0 -0
- package/dashboard/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dashboard/assets/jetbrains-mono-latin-wght-italic-B2M6KQje.woff2 +0 -0
- package/dashboard/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dashboard/assets/leaflet-CIGW-MKW.css +1 -0
- package/dashboard/assets/leaflet-src-D12shr04.js +2 -0
- package/dashboard/assets/leaflet-src-D12shr04.js.map +1 -0
- package/dashboard/assets/manrope-latin-ext-wght-normal-Ch3YOpNY.woff2 +0 -0
- package/dashboard/assets/manrope-latin-wght-normal-DHIcAJRg.woff2 +0 -0
- package/dashboard/assets/media-track-components-CpeII-tT.js +2 -0
- package/dashboard/assets/media-track-components-CpeII-tT.js.map +1 -0
- package/dashboard/assets/scales-e0tkfEy1.js +2 -0
- package/dashboard/assets/scales-e0tkfEy1.js.map +1 -0
- package/dashboard/assets/sparkline-2JUGDrMW.js +2 -0
- package/dashboard/assets/sparkline-2JUGDrMW.js.map +1 -0
- package/dashboard/assets/stats-BNgXz5BD.js +2 -0
- package/dashboard/assets/stats-BNgXz5BD.js.map +1 -0
- package/dashboard/assets/studio-B7hMOwAF.js +2 -0
- package/dashboard/assets/studio-B7hMOwAF.js.map +1 -0
- package/dashboard/assets/studio-BN_9xHY3.js +2 -0
- package/dashboard/assets/studio-BN_9xHY3.js.map +1 -0
- package/dashboard/assets/studio-Cn2MObe8.js +2 -0
- package/dashboard/assets/studio-Cn2MObe8.js.map +1 -0
- package/dashboard/assets/studio-DZEZCCkw.js +2 -0
- package/dashboard/assets/studio-DZEZCCkw.js.map +1 -0
- package/dashboard/assets/studio-DzatTvLl.js +2 -0
- package/dashboard/assets/studio-DzatTvLl.js.map +1 -0
- package/dashboard/assets/studio-cBlD8x90.js +2 -0
- package/dashboard/assets/studio-cBlD8x90.js.map +1 -0
- package/dashboard/assets/studio-cglZPbJK.js +2 -0
- package/dashboard/assets/studio-cglZPbJK.js.map +1 -0
- package/dashboard/assets/system-track-components-GTYYpnfB.js +2 -0
- package/dashboard/assets/system-track-components-GTYYpnfB.js.map +1 -0
- package/dashboard/assets/tables-tail-components-DiA5GeHB.js +2 -0
- package/dashboard/assets/tables-tail-components-DiA5GeHB.js.map +1 -0
- package/dashboard/assets/tables-track-f-components-CVNPd7rq.js +2 -0
- package/dashboard/assets/tables-track-f-components-CVNPd7rq.js.map +1 -0
- package/dashboard/assets/time-flow-components-nKsaryry.js +2 -0
- package/dashboard/assets/time-flow-components-nKsaryry.js.map +1 -0
- package/dashboard/assets/ui-B-kZetor.js +2 -0
- package/dashboard/assets/ui-B-kZetor.js.map +1 -0
- package/dashboard/assets/ui-BEStJ5Pw.js +2 -0
- package/dashboard/assets/ui-BEStJ5Pw.js.map +1 -0
- package/dashboard/assets/ui-BS5_eDN4.js +2 -0
- package/dashboard/assets/ui-BS5_eDN4.js.map +1 -0
- package/dashboard/assets/ui-BZ0EyxRH.js +2 -0
- package/dashboard/assets/ui-BZ0EyxRH.js.map +1 -0
- package/dashboard/assets/ui-BloJDdt6.js +2 -0
- package/dashboard/assets/ui-BloJDdt6.js.map +1 -0
- package/dashboard/assets/ui-CpdrplJH.js +2 -0
- package/dashboard/assets/ui-CpdrplJH.js.map +1 -0
- package/dashboard/assets/ui-YJfT644k.js +2 -0
- package/dashboard/assets/ui-YJfT644k.js.map +1 -0
- package/dashboard/assets/widgets-uDqZWw4A.js +2 -0
- package/dashboard/assets/widgets-uDqZWw4A.js.map +1 -0
- package/dashboard/index.html +41 -0
- package/dist/app.d.ts +48 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +250 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/audit.d.ts +22 -0
- package/dist/auth/audit.d.ts.map +1 -0
- package/dist/auth/audit.js +17 -0
- package/dist/auth/audit.js.map +1 -0
- package/dist/auth/desktop-session.d.ts +53 -0
- package/dist/auth/desktop-session.d.ts.map +1 -0
- package/dist/auth/desktop-session.js +111 -0
- package/dist/auth/desktop-session.js.map +1 -0
- package/dist/auth/passwords.d.ts +17 -0
- package/dist/auth/passwords.d.ts.map +1 -0
- package/dist/auth/passwords.js +40 -0
- package/dist/auth/passwords.js.map +1 -0
- package/dist/auth/sessions.d.ts +77 -0
- package/dist/auth/sessions.d.ts.map +1 -0
- package/dist/auth/sessions.js +137 -0
- package/dist/auth/sessions.js.map +1 -0
- package/dist/auth/totp.d.ts +30 -0
- package/dist/auth/totp.d.ts.map +1 -0
- package/dist/auth/totp.js +97 -0
- package/dist/auth/totp.js.map +1 -0
- package/dist/backup/backup-service.d.ts +157 -0
- package/dist/backup/backup-service.d.ts.map +1 -0
- package/dist/backup/backup-service.js +354 -0
- package/dist/backup/backup-service.js.map +1 -0
- package/dist/backup/format.d.ts +300 -0
- package/dist/backup/format.d.ts.map +1 -0
- package/dist/backup/format.js +304 -0
- package/dist/backup/format.js.map +1 -0
- package/dist/backup/notify.d.ts +55 -0
- package/dist/backup/notify.d.ts.map +1 -0
- package/dist/backup/notify.js +60 -0
- package/dist/backup/notify.js.map +1 -0
- package/dist/backup/snapshot.d.ts +78 -0
- package/dist/backup/snapshot.d.ts.map +1 -0
- package/dist/backup/snapshot.js +142 -0
- package/dist/backup/snapshot.js.map +1 -0
- package/dist/capabilities/catalog.d.ts +33 -0
- package/dist/capabilities/catalog.d.ts.map +1 -0
- package/dist/capabilities/catalog.js +32 -0
- package/dist/capabilities/catalog.js.map +1 -0
- package/dist/capabilities/grants.d.ts +44 -0
- package/dist/capabilities/grants.d.ts.map +1 -0
- package/dist/capabilities/grants.js +65 -0
- package/dist/capabilities/grants.js.map +1 -0
- package/dist/cli/allowlist.d.ts +46 -0
- package/dist/cli/allowlist.d.ts.map +1 -0
- package/dist/cli/allowlist.js +99 -0
- package/dist/cli/allowlist.js.map +1 -0
- package/dist/cli/args.d.ts +63 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +92 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/command.d.ts +32 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +64 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/commands/apply-llm-response.d.ts +32 -0
- package/dist/cli/commands/apply-llm-response.d.ts.map +1 -0
- package/dist/cli/commands/apply-llm-response.js +209 -0
- package/dist/cli/commands/apply-llm-response.js.map +1 -0
- package/dist/cli/commands/export-zip.d.ts +17 -0
- package/dist/cli/commands/export-zip.d.ts.map +1 -0
- package/dist/cli/commands/export-zip.js +111 -0
- package/dist/cli/commands/export-zip.js.map +1 -0
- package/dist/cli/commands/generate-prompt.d.ts +29 -0
- package/dist/cli/commands/generate-prompt.d.ts.map +1 -0
- package/dist/cli/commands/generate-prompt.js +154 -0
- package/dist/cli/commands/generate-prompt.js.map +1 -0
- package/dist/cli/commands/import-zip.d.ts +13 -0
- package/dist/cli/commands/import-zip.d.ts.map +1 -0
- package/dist/cli/commands/import-zip.js +95 -0
- package/dist/cli/commands/import-zip.js.map +1 -0
- package/dist/cli/commands/init.d.ts +47 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +372 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/introspect.d.ts +11 -0
- package/dist/cli/commands/introspect.d.ts.map +1 -0
- package/dist/cli/commands/introspect.js +100 -0
- package/dist/cli/commands/introspect.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +11 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +80 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/start.d.ts +22 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +101 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/exit.d.ts +37 -0
- package/dist/cli/exit.d.ts.map +1 -0
- package/dist/cli/exit.js +39 -0
- package/dist/cli/exit.js.map +1 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +17 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/io.d.ts +49 -0
- package/dist/cli/io.d.ts.map +1 -0
- package/dist/cli/io.js +77 -0
- package/dist/cli/io.js.map +1 -0
- package/dist/cli/run.d.ts +35 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +139 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/runtime.d.ts +116 -0
- package/dist/cli/runtime.d.ts.map +1 -0
- package/dist/cli/runtime.js +181 -0
- package/dist/cli/runtime.js.map +1 -0
- package/dist/cli/static-root.d.ts +42 -0
- package/dist/cli/static-root.d.ts.map +1 -0
- package/dist/cli/static-root.js +58 -0
- package/dist/cli/static-root.js.map +1 -0
- package/dist/compose.d.ts +135 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +383 -0
- package/dist/compose.js.map +1 -0
- package/dist/config/bootstrap.d.ts +33 -0
- package/dist/config/bootstrap.d.ts.map +1 -0
- package/dist/config/bootstrap.js +81 -0
- package/dist/config/bootstrap.js.map +1 -0
- package/dist/config/env.d.ts +95 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +236 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/secrets.d.ts +24 -0
- package/dist/config/secrets.d.ts.map +1 -0
- package/dist/config/secrets.js +74 -0
- package/dist/config/secrets.js.map +1 -0
- package/dist/connections/crypto.d.ts +9 -0
- package/dist/connections/crypto.d.ts.map +1 -0
- package/dist/connections/crypto.js +16 -0
- package/dist/connections/crypto.js.map +1 -0
- package/dist/connections/dsn.d.ts +42 -0
- package/dist/connections/dsn.d.ts.map +1 -0
- package/dist/connections/dsn.js +131 -0
- package/dist/connections/dsn.js.map +1 -0
- package/dist/connections/effective-schema.d.ts +65 -0
- package/dist/connections/effective-schema.d.ts.map +1 -0
- package/dist/connections/effective-schema.js +249 -0
- package/dist/connections/effective-schema.js.map +1 -0
- package/dist/connections/introspect.d.ts +52 -0
- package/dist/connections/introspect.d.ts.map +1 -0
- package/dist/connections/introspect.js +111 -0
- package/dist/connections/introspect.js.map +1 -0
- package/dist/connections/manager.d.ts +97 -0
- package/dist/connections/manager.d.ts.map +1 -0
- package/dist/connections/manager.js +224 -0
- package/dist/connections/manager.js.map +1 -0
- package/dist/connections/register-adapters.d.ts +42 -0
- package/dist/connections/register-adapters.d.ts.map +1 -0
- package/dist/connections/register-adapters.js +92 -0
- package/dist/connections/register-adapters.js.map +1 -0
- package/dist/crud/filters.d.ts +57 -0
- package/dist/crud/filters.d.ts.map +1 -0
- package/dist/crud/filters.js +177 -0
- package/dist/crud/filters.js.map +1 -0
- package/dist/crud/identifiers.d.ts +58 -0
- package/dist/crud/identifiers.d.ts.map +1 -0
- package/dist/crud/identifiers.js +99 -0
- package/dist/crud/identifiers.js.map +1 -0
- package/dist/crud/list.d.ts +51 -0
- package/dist/crud/list.d.ts.map +1 -0
- package/dist/crud/list.js +126 -0
- package/dist/crud/list.js.map +1 -0
- package/dist/crud/mask.d.ts +23 -0
- package/dist/crud/mask.d.ts.map +1 -0
- package/dist/crud/mask.js +41 -0
- package/dist/crud/mask.js.map +1 -0
- package/dist/crud/records.d.ts +33 -0
- package/dist/crud/records.d.ts.map +1 -0
- package/dist/crud/records.js +126 -0
- package/dist/crud/records.js.map +1 -0
- package/dist/crud/undo.d.ts +55 -0
- package/dist/crud/undo.d.ts.map +1 -0
- package/dist/crud/undo.js +74 -0
- package/dist/crud/undo.js.map +1 -0
- package/dist/data-io/coerce.d.ts +28 -0
- package/dist/data-io/coerce.d.ts.map +1 -0
- package/dist/data-io/coerce.js +123 -0
- package/dist/data-io/coerce.js.map +1 -0
- package/dist/data-io/csv.d.ts +38 -0
- package/dist/data-io/csv.d.ts.map +1 -0
- package/dist/data-io/csv.js +138 -0
- package/dist/data-io/csv.js.map +1 -0
- package/dist/data-io/snapshot-view.d.ts +10 -0
- package/dist/data-io/snapshot-view.d.ts.map +1 -0
- package/dist/data-io/snapshot-view.js +19 -0
- package/dist/data-io/snapshot-view.js.map +1 -0
- package/dist/desktop/demo-seed.d.ts +23 -0
- package/dist/desktop/demo-seed.d.ts.map +1 -0
- package/dist/desktop/demo-seed.js +28 -0
- package/dist/desktop/demo-seed.js.map +1 -0
- package/dist/desktop/lan-share.d.ts +94 -0
- package/dist/desktop/lan-share.d.ts.map +1 -0
- package/dist/desktop/lan-share.js +150 -0
- package/dist/desktop/lan-share.js.map +1 -0
- package/dist/errors.d.ts +72 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +82 -0
- package/dist/errors.js.map +1 -0
- package/dist/export/bundle.d.ts +235 -0
- package/dist/export/bundle.d.ts.map +1 -0
- package/dist/export/bundle.js +172 -0
- package/dist/export/bundle.js.map +1 -0
- package/dist/export/import-service.d.ts +99 -0
- package/dist/export/import-service.d.ts.map +1 -0
- package/dist/export/import-service.js +515 -0
- package/dist/export/import-service.js.map +1 -0
- package/dist/export/readme.d.ts +25 -0
- package/dist/export/readme.d.ts.map +1 -0
- package/dist/export/readme.js +154 -0
- package/dist/export/readme.js.map +1 -0
- package/dist/export/redaction.d.ts +118 -0
- package/dist/export/redaction.d.ts.map +1 -0
- package/dist/export/redaction.js +233 -0
- package/dist/export/redaction.js.map +1 -0
- package/dist/export/zip-service.d.ts +66 -0
- package/dist/export/zip-service.d.ts.map +1 -0
- package/dist/export/zip-service.js +306 -0
- package/dist/export/zip-service.js.map +1 -0
- package/dist/files/storage.d.ts +50 -0
- package/dist/files/storage.d.ts.map +1 -0
- package/dist/files/storage.js +100 -0
- package/dist/files/storage.js.map +1 -0
- package/dist/generate/materialize-llm.d.ts +45 -0
- package/dist/generate/materialize-llm.d.ts.map +1 -0
- package/dist/generate/materialize-llm.js +167 -0
- package/dist/generate/materialize-llm.js.map +1 -0
- package/dist/generate/run.d.ts +48 -0
- package/dist/generate/run.d.ts.map +1 -0
- package/dist/generate/run.js +123 -0
- package/dist/generate/run.js.map +1 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/export-run.d.ts +38 -0
- package/dist/jobs/export-run.d.ts.map +1 -0
- package/dist/jobs/export-run.js +172 -0
- package/dist/jobs/export-run.js.map +1 -0
- package/dist/jobs/import-run.d.ts +43 -0
- package/dist/jobs/import-run.d.ts.map +1 -0
- package/dist/jobs/import-run.js +290 -0
- package/dist/jobs/import-run.js.map +1 -0
- package/dist/jobs/llm-run.d.ts +73 -0
- package/dist/jobs/llm-run.d.ts.map +1 -0
- package/dist/jobs/llm-run.js +225 -0
- package/dist/jobs/llm-run.js.map +1 -0
- package/dist/jobs/register.d.ts +90 -0
- package/dist/jobs/register.d.ts.map +1 -0
- package/dist/jobs/register.js +121 -0
- package/dist/jobs/register.js.map +1 -0
- package/dist/jobs/registry.d.ts +74 -0
- package/dist/jobs/registry.d.ts.map +1 -0
- package/dist/jobs/registry.js +78 -0
- package/dist/jobs/registry.js.map +1 -0
- package/dist/jobs/report-run.d.ts +64 -0
- package/dist/jobs/report-run.d.ts.map +1 -0
- package/dist/jobs/report-run.js +221 -0
- package/dist/jobs/report-run.js.map +1 -0
- package/dist/jobs/scheduler.d.ts +72 -0
- package/dist/jobs/scheduler.d.ts.map +1 -0
- package/dist/jobs/scheduler.js +121 -0
- package/dist/jobs/scheduler.js.map +1 -0
- package/dist/jobs/worker.d.ts +110 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/jobs/worker.js +282 -0
- package/dist/jobs/worker.js.map +1 -0
- package/dist/llm/apply-service.d.ts +150 -0
- package/dist/llm/apply-service.d.ts.map +1 -0
- package/dist/llm/apply-service.js +463 -0
- package/dist/llm/apply-service.js.map +1 -0
- package/dist/llm/apply-undo-store.d.ts +50 -0
- package/dist/llm/apply-undo-store.d.ts.map +1 -0
- package/dist/llm/apply-undo-store.js +60 -0
- package/dist/llm/apply-undo-store.js.map +1 -0
- package/dist/llm/direct-runner.d.ts +146 -0
- package/dist/llm/direct-runner.d.ts.map +1 -0
- package/dist/llm/direct-runner.js +204 -0
- package/dist/llm/direct-runner.js.map +1 -0
- package/dist/llm/prompt-service.d.ts +90 -0
- package/dist/llm/prompt-service.d.ts.map +1 -0
- package/dist/llm/prompt-service.js +93 -0
- package/dist/llm/prompt-service.js.map +1 -0
- package/dist/llm/provider-resolver.d.ts +25 -0
- package/dist/llm/provider-resolver.d.ts.map +1 -0
- package/dist/llm/provider-resolver.js +81 -0
- package/dist/llm/provider-resolver.js.map +1 -0
- package/dist/llm/run-service.d.ts +215 -0
- package/dist/llm/run-service.d.ts.map +1 -0
- package/dist/llm/run-service.js +343 -0
- package/dist/llm/run-service.js.map +1 -0
- package/dist/llm/stats-collector.d.ts +40 -0
- package/dist/llm/stats-collector.d.ts.map +1 -0
- package/dist/llm/stats-collector.js +74 -0
- package/dist/llm/stats-collector.js.map +1 -0
- package/dist/log-scrub.d.ts +58 -0
- package/dist/log-scrub.d.ts.map +1 -0
- package/dist/log-scrub.js +103 -0
- package/dist/log-scrub.js.map +1 -0
- package/dist/meta/store.d.ts +96 -0
- package/dist/meta/store.d.ts.map +1 -0
- package/dist/meta/store.js +192 -0
- package/dist/meta/store.js.map +1 -0
- package/dist/notifications/notify.d.ts +43 -0
- package/dist/notifications/notify.d.ts.map +1 -0
- package/dist/notifications/notify.js +42 -0
- package/dist/notifications/notify.js.map +1 -0
- package/dist/plugins/auth.d.ts +42 -0
- package/dist/plugins/auth.d.ts.map +1 -0
- package/dist/plugins/auth.js +84 -0
- package/dist/plugins/auth.js.map +1 -0
- package/dist/plugins/core.d.ts +48 -0
- package/dist/plugins/core.d.ts.map +1 -0
- package/dist/plugins/core.js +248 -0
- package/dist/plugins/core.js.map +1 -0
- package/dist/plugins/rbac.d.ts +54 -0
- package/dist/plugins/rbac.d.ts.map +1 -0
- package/dist/plugins/rbac.js +103 -0
- package/dist/plugins/rbac.js.map +1 -0
- package/dist/plugins/static.d.ts +12 -0
- package/dist/plugins/static.d.ts.map +1 -0
- package/dist/plugins/static.js +36 -0
- package/dist/plugins/static.js.map +1 -0
- package/dist/rbac/api-keys.d.ts +30 -0
- package/dist/rbac/api-keys.d.ts.map +1 -0
- package/dist/rbac/api-keys.js +41 -0
- package/dist/rbac/api-keys.js.map +1 -0
- package/dist/rbac/index.d.ts +6 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +6 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/permissions.d.ts +107 -0
- package/dist/rbac/permissions.d.ts.map +1 -0
- package/dist/rbac/permissions.js +250 -0
- package/dist/rbac/permissions.js.map +1 -0
- package/dist/rbac/principal.d.ts +33 -0
- package/dist/rbac/principal.d.ts.map +1 -0
- package/dist/rbac/principal.js +31 -0
- package/dist/rbac/principal.js.map +1 -0
- package/dist/rbac/resolver.d.ts +26 -0
- package/dist/rbac/resolver.d.ts.map +1 -0
- package/dist/rbac/resolver.js +46 -0
- package/dist/rbac/resolver.js.map +1 -0
- package/dist/realtime/hub.d.ts +90 -0
- package/dist/realtime/hub.d.ts.map +1 -0
- package/dist/realtime/hub.js +146 -0
- package/dist/realtime/hub.js.map +1 -0
- package/dist/realtime/sse.d.ts +35 -0
- package/dist/realtime/sse.d.ts.map +1 -0
- package/dist/realtime/sse.js +88 -0
- package/dist/realtime/sse.js.map +1 -0
- package/dist/realtime/ws.d.ts +38 -0
- package/dist/realtime/ws.d.ts.map +1 -0
- package/dist/realtime/ws.js +124 -0
- package/dist/realtime/ws.js.map +1 -0
- package/dist/reports/schedule.d.ts +14 -0
- package/dist/reports/schedule.d.ts.map +1 -0
- package/dist/reports/schedule.js +63 -0
- package/dist/reports/schedule.js.map +1 -0
- package/dist/routes/about/index.d.ts +39 -0
- package/dist/routes/about/index.d.ts.map +1 -0
- package/dist/routes/about/index.js +73 -0
- package/dist/routes/about/index.js.map +1 -0
- package/dist/routes/about/schema.d.ts +50 -0
- package/dist/routes/about/schema.d.ts.map +1 -0
- package/dist/routes/about/schema.js +53 -0
- package/dist/routes/about/schema.js.map +1 -0
- package/dist/routes/api-keys/index.d.ts +11 -0
- package/dist/routes/api-keys/index.d.ts.map +1 -0
- package/dist/routes/api-keys/index.js +79 -0
- package/dist/routes/api-keys/index.js.map +1 -0
- package/dist/routes/api-keys/schema.d.ts +62 -0
- package/dist/routes/api-keys/schema.d.ts.map +1 -0
- package/dist/routes/api-keys/schema.js +37 -0
- package/dist/routes/api-keys/schema.js.map +1 -0
- package/dist/routes/audit/index.d.ts +11 -0
- package/dist/routes/audit/index.d.ts.map +1 -0
- package/dist/routes/audit/index.js +107 -0
- package/dist/routes/audit/index.js.map +1 -0
- package/dist/routes/audit/schema.d.ts +129 -0
- package/dist/routes/audit/schema.d.ts.map +1 -0
- package/dist/routes/audit/schema.js +43 -0
- package/dist/routes/audit/schema.js.map +1 -0
- package/dist/routes/auth/desktop-session.d.ts +48 -0
- package/dist/routes/auth/desktop-session.d.ts.map +1 -0
- package/dist/routes/auth/desktop-session.js +132 -0
- package/dist/routes/auth/desktop-session.js.map +1 -0
- package/dist/routes/auth/handlers.d.ts +21 -0
- package/dist/routes/auth/handlers.d.ts.map +1 -0
- package/dist/routes/auth/handlers.js +256 -0
- package/dist/routes/auth/handlers.js.map +1 -0
- package/dist/routes/auth/index.d.ts +27 -0
- package/dist/routes/auth/index.d.ts.map +1 -0
- package/dist/routes/auth/index.js +67 -0
- package/dist/routes/auth/index.js.map +1 -0
- package/dist/routes/auth/schema.d.ts +129 -0
- package/dist/routes/auth/schema.d.ts.map +1 -0
- package/dist/routes/auth/schema.js +84 -0
- package/dist/routes/auth/schema.js.map +1 -0
- package/dist/routes/bootstrap/handlers.d.ts +34 -0
- package/dist/routes/bootstrap/handlers.d.ts.map +1 -0
- package/dist/routes/bootstrap/handlers.js +96 -0
- package/dist/routes/bootstrap/handlers.js.map +1 -0
- package/dist/routes/bootstrap/index.d.ts +9 -0
- package/dist/routes/bootstrap/index.d.ts.map +1 -0
- package/dist/routes/bootstrap/index.js +16 -0
- package/dist/routes/bootstrap/index.js.map +1 -0
- package/dist/routes/bootstrap/schema.d.ts +177 -0
- package/dist/routes/bootstrap/schema.d.ts.map +1 -0
- package/dist/routes/bootstrap/schema.js +55 -0
- package/dist/routes/bootstrap/schema.js.map +1 -0
- package/dist/routes/connections/index.d.ts +21 -0
- package/dist/routes/connections/index.d.ts.map +1 -0
- package/dist/routes/connections/index.js +260 -0
- package/dist/routes/connections/index.js.map +1 -0
- package/dist/routes/connections/schema.d.ts +161 -0
- package/dist/routes/connections/schema.d.ts.map +1 -0
- package/dist/routes/connections/schema.js +91 -0
- package/dist/routes/connections/schema.js.map +1 -0
- package/dist/routes/data/index.d.ts +46 -0
- package/dist/routes/data/index.d.ts.map +1 -0
- package/dist/routes/data/index.js +508 -0
- package/dist/routes/data/index.js.map +1 -0
- package/dist/routes/data/schema.d.ts +128 -0
- package/dist/routes/data/schema.d.ts.map +1 -0
- package/dist/routes/data/schema.js +83 -0
- package/dist/routes/data/schema.js.map +1 -0
- package/dist/routes/desktop/index.d.ts +61 -0
- package/dist/routes/desktop/index.d.ts.map +1 -0
- package/dist/routes/desktop/index.js +91 -0
- package/dist/routes/desktop/index.js.map +1 -0
- package/dist/routes/desktop/schema.d.ts +71 -0
- package/dist/routes/desktop/schema.d.ts.map +1 -0
- package/dist/routes/desktop/schema.js +58 -0
- package/dist/routes/desktop/schema.js.map +1 -0
- package/dist/routes/desktop-capabilities/index.d.ts +9 -0
- package/dist/routes/desktop-capabilities/index.d.ts.map +1 -0
- package/dist/routes/desktop-capabilities/index.js +62 -0
- package/dist/routes/desktop-capabilities/index.js.map +1 -0
- package/dist/routes/desktop-capabilities/schema.d.ts +46 -0
- package/dist/routes/desktop-capabilities/schema.d.ts.map +1 -0
- package/dist/routes/desktop-capabilities/schema.js +30 -0
- package/dist/routes/desktop-capabilities/schema.js.map +1 -0
- package/dist/routes/desktop-demo/handlers.d.ts +94 -0
- package/dist/routes/desktop-demo/handlers.d.ts.map +1 -0
- package/dist/routes/desktop-demo/handlers.js +182 -0
- package/dist/routes/desktop-demo/handlers.js.map +1 -0
- package/dist/routes/desktop-demo/index.d.ts +39 -0
- package/dist/routes/desktop-demo/index.d.ts.map +1 -0
- package/dist/routes/desktop-demo/index.js +73 -0
- package/dist/routes/desktop-demo/index.js.map +1 -0
- package/dist/routes/desktop-demo/schema.d.ts +17 -0
- package/dist/routes/desktop-demo/schema.d.ts.map +1 -0
- package/dist/routes/desktop-demo/schema.js +30 -0
- package/dist/routes/desktop-demo/schema.js.map +1 -0
- package/dist/routes/desktop-lan/index.d.ts +54 -0
- package/dist/routes/desktop-lan/index.d.ts.map +1 -0
- package/dist/routes/desktop-lan/index.js +33 -0
- package/dist/routes/desktop-lan/index.js.map +1 -0
- package/dist/routes/desktop-lan/schema.d.ts +24 -0
- package/dist/routes/desktop-lan/schema.d.ts.map +1 -0
- package/dist/routes/desktop-lan/schema.js +40 -0
- package/dist/routes/desktop-lan/schema.js.map +1 -0
- package/dist/routes/desktop-local-db/handlers.d.ts +92 -0
- package/dist/routes/desktop-local-db/handlers.d.ts.map +1 -0
- package/dist/routes/desktop-local-db/handlers.js +300 -0
- package/dist/routes/desktop-local-db/handlers.js.map +1 -0
- package/dist/routes/desktop-local-db/index.d.ts +39 -0
- package/dist/routes/desktop-local-db/index.d.ts.map +1 -0
- package/dist/routes/desktop-local-db/index.js +83 -0
- package/dist/routes/desktop-local-db/index.js.map +1 -0
- package/dist/routes/desktop-local-db/placeholder.d.ts +75 -0
- package/dist/routes/desktop-local-db/placeholder.d.ts.map +1 -0
- package/dist/routes/desktop-local-db/placeholder.js +420 -0
- package/dist/routes/desktop-local-db/placeholder.js.map +1 -0
- package/dist/routes/desktop-local-db/schema.d.ts +50 -0
- package/dist/routes/desktop-local-db/schema.d.ts.map +1 -0
- package/dist/routes/desktop-local-db/schema.js +71 -0
- package/dist/routes/desktop-local-db/schema.js.map +1 -0
- package/dist/routes/desktop-local-db/sqlite-ddl.d.ts +104 -0
- package/dist/routes/desktop-local-db/sqlite-ddl.d.ts.map +1 -0
- package/dist/routes/desktop-local-db/sqlite-ddl.js +419 -0
- package/dist/routes/desktop-local-db/sqlite-ddl.js.map +1 -0
- package/dist/routes/email-templates/index.d.ts +7 -0
- package/dist/routes/email-templates/index.d.ts.map +1 -0
- package/dist/routes/email-templates/index.js +70 -0
- package/dist/routes/email-templates/index.js.map +1 -0
- package/dist/routes/email-templates/schema.d.ts +54 -0
- package/dist/routes/email-templates/schema.d.ts.map +1 -0
- package/dist/routes/email-templates/schema.js +35 -0
- package/dist/routes/email-templates/schema.js.map +1 -0
- package/dist/routes/exports/index.d.ts +19 -0
- package/dist/routes/exports/index.d.ts.map +1 -0
- package/dist/routes/exports/index.js +145 -0
- package/dist/routes/exports/index.js.map +1 -0
- package/dist/routes/exports/schema.d.ts +183 -0
- package/dist/routes/exports/schema.d.ts.map +1 -0
- package/dist/routes/exports/schema.js +37 -0
- package/dist/routes/exports/schema.js.map +1 -0
- package/dist/routes/generate/index.d.ts +23 -0
- package/dist/routes/generate/index.d.ts.map +1 -0
- package/dist/routes/generate/index.js +80 -0
- package/dist/routes/generate/index.js.map +1 -0
- package/dist/routes/generate/schema.d.ts +43 -0
- package/dist/routes/generate/schema.d.ts.map +1 -0
- package/dist/routes/generate/schema.js +37 -0
- package/dist/routes/generate/schema.js.map +1 -0
- package/dist/routes/imports/index.d.ts +21 -0
- package/dist/routes/imports/index.d.ts.map +1 -0
- package/dist/routes/imports/index.js +288 -0
- package/dist/routes/imports/index.js.map +1 -0
- package/dist/routes/imports/schema.d.ts +292 -0
- package/dist/routes/imports/schema.d.ts.map +1 -0
- package/dist/routes/imports/schema.js +78 -0
- package/dist/routes/imports/schema.js.map +1 -0
- package/dist/routes/index.d.ts +11 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +8 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/jobs/index.d.ts +29 -0
- package/dist/routes/jobs/index.d.ts.map +1 -0
- package/dist/routes/jobs/index.js +175 -0
- package/dist/routes/jobs/index.js.map +1 -0
- package/dist/routes/jobs/schema.d.ts +170 -0
- package/dist/routes/jobs/schema.d.ts.map +1 -0
- package/dist/routes/jobs/schema.js +57 -0
- package/dist/routes/jobs/schema.js.map +1 -0
- package/dist/routes/llm/config-service.d.ts +48 -0
- package/dist/routes/llm/config-service.d.ts.map +1 -0
- package/dist/routes/llm/config-service.js +102 -0
- package/dist/routes/llm/config-service.js.map +1 -0
- package/dist/routes/llm/index.d.ts +69 -0
- package/dist/routes/llm/index.d.ts.map +1 -0
- package/dist/routes/llm/index.js +412 -0
- package/dist/routes/llm/index.js.map +1 -0
- package/dist/routes/llm/schema.d.ts +605 -0
- package/dist/routes/llm/schema.d.ts.map +1 -0
- package/dist/routes/llm/schema.js +238 -0
- package/dist/routes/llm/schema.js.map +1 -0
- package/dist/routes/me/handlers.d.ts +14 -0
- package/dist/routes/me/handlers.d.ts.map +1 -0
- package/dist/routes/me/handlers.js +88 -0
- package/dist/routes/me/handlers.js.map +1 -0
- package/dist/routes/me/index.d.ts +8 -0
- package/dist/routes/me/index.d.ts.map +1 -0
- package/dist/routes/me/index.js +17 -0
- package/dist/routes/me/index.js.map +1 -0
- package/dist/routes/me/schema.d.ts +270 -0
- package/dist/routes/me/schema.d.ts.map +1 -0
- package/dist/routes/me/schema.js +59 -0
- package/dist/routes/me/schema.js.map +1 -0
- package/dist/routes/me-views/index.d.ts +23 -0
- package/dist/routes/me-views/index.d.ts.map +1 -0
- package/dist/routes/me-views/index.js +76 -0
- package/dist/routes/me-views/index.js.map +1 -0
- package/dist/routes/me-views/schema.d.ts +44 -0
- package/dist/routes/me-views/schema.d.ts.map +1 -0
- package/dist/routes/me-views/schema.js +13 -0
- package/dist/routes/me-views/schema.js.map +1 -0
- package/dist/routes/notifications/index.d.ts +19 -0
- package/dist/routes/notifications/index.d.ts.map +1 -0
- package/dist/routes/notifications/index.js +123 -0
- package/dist/routes/notifications/index.js.map +1 -0
- package/dist/routes/notifications/schema.d.ts +122 -0
- package/dist/routes/notifications/schema.d.ts.map +1 -0
- package/dist/routes/notifications/schema.js +83 -0
- package/dist/routes/notifications/schema.js.map +1 -0
- package/dist/routes/onboarding/derive.d.ts +41 -0
- package/dist/routes/onboarding/derive.d.ts.map +1 -0
- package/dist/routes/onboarding/derive.js +30 -0
- package/dist/routes/onboarding/derive.js.map +1 -0
- package/dist/routes/onboarding/index.d.ts +26 -0
- package/dist/routes/onboarding/index.d.ts.map +1 -0
- package/dist/routes/onboarding/index.js +95 -0
- package/dist/routes/onboarding/index.js.map +1 -0
- package/dist/routes/onboarding/schema.d.ts +22 -0
- package/dist/routes/onboarding/schema.d.ts.map +1 -0
- package/dist/routes/onboarding/schema.js +22 -0
- package/dist/routes/onboarding/schema.js.map +1 -0
- package/dist/routes/pages/index.d.ts +26 -0
- package/dist/routes/pages/index.d.ts.map +1 -0
- package/dist/routes/pages/index.js +119 -0
- package/dist/routes/pages/index.js.map +1 -0
- package/dist/routes/pages/layout-schema.d.ts +19 -0
- package/dist/routes/pages/layout-schema.d.ts.map +1 -0
- package/dist/routes/pages/layout-schema.js +19 -0
- package/dist/routes/pages/layout-schema.js.map +1 -0
- package/dist/routes/pages/schema.d.ts +52 -0
- package/dist/routes/pages/schema.d.ts.map +1 -0
- package/dist/routes/pages/schema.js +35 -0
- package/dist/routes/pages/schema.js.map +1 -0
- package/dist/routes/roles/index.d.ts +17 -0
- package/dist/routes/roles/index.d.ts.map +1 -0
- package/dist/routes/roles/index.js +255 -0
- package/dist/routes/roles/index.js.map +1 -0
- package/dist/routes/roles/schema.d.ts +94 -0
- package/dist/routes/roles/schema.d.ts.map +1 -0
- package/dist/routes/roles/schema.js +57 -0
- package/dist/routes/roles/schema.js.map +1 -0
- package/dist/routes/scheduled-reports/index.d.ts +15 -0
- package/dist/routes/scheduled-reports/index.d.ts.map +1 -0
- package/dist/routes/scheduled-reports/index.js +195 -0
- package/dist/routes/scheduled-reports/index.js.map +1 -0
- package/dist/routes/scheduled-reports/schema.d.ts +154 -0
- package/dist/routes/scheduled-reports/schema.d.ts.map +1 -0
- package/dist/routes/scheduled-reports/schema.js +49 -0
- package/dist/routes/scheduled-reports/schema.js.map +1 -0
- package/dist/routes/schema/index.d.ts +24 -0
- package/dist/routes/schema/index.d.ts.map +1 -0
- package/dist/routes/schema/index.js +224 -0
- package/dist/routes/schema/index.js.map +1 -0
- package/dist/routes/schema/schema.d.ts +92 -0
- package/dist/routes/schema/schema.d.ts.map +1 -0
- package/dist/routes/schema/schema.js +64 -0
- package/dist/routes/schema/schema.js.map +1 -0
- package/dist/routes/schema-import/fallback-parser.d.ts +35 -0
- package/dist/routes/schema-import/fallback-parser.d.ts.map +1 -0
- package/dist/routes/schema-import/fallback-parser.js +349 -0
- package/dist/routes/schema-import/fallback-parser.js.map +1 -0
- package/dist/routes/schema-import/index.d.ts +43 -0
- package/dist/routes/schema-import/index.d.ts.map +1 -0
- package/dist/routes/schema-import/index.js +167 -0
- package/dist/routes/schema-import/index.js.map +1 -0
- package/dist/routes/schema-import/schema.d.ts +65 -0
- package/dist/routes/schema-import/schema.d.ts.map +1 -0
- package/dist/routes/schema-import/schema.js +40 -0
- package/dist/routes/schema-import/schema.js.map +1 -0
- package/dist/routes/search/index.d.ts +71 -0
- package/dist/routes/search/index.d.ts.map +1 -0
- package/dist/routes/search/index.js +361 -0
- package/dist/routes/search/index.js.map +1 -0
- package/dist/routes/search/schema.d.ts +125 -0
- package/dist/routes/search/schema.d.ts.map +1 -0
- package/dist/routes/search/schema.js +70 -0
- package/dist/routes/search/schema.js.map +1 -0
- package/dist/routes/settings/index.d.ts +24 -0
- package/dist/routes/settings/index.d.ts.map +1 -0
- package/dist/routes/settings/index.js +164 -0
- package/dist/routes/settings/index.js.map +1 -0
- package/dist/routes/settings/schema.d.ts +110 -0
- package/dist/routes/settings/schema.d.ts.map +1 -0
- package/dist/routes/settings/schema.js +71 -0
- package/dist/routes/settings/schema.js.map +1 -0
- package/dist/routes/setup/index.d.ts +29 -0
- package/dist/routes/setup/index.d.ts.map +1 -0
- package/dist/routes/setup/index.js +68 -0
- package/dist/routes/setup/index.js.map +1 -0
- package/dist/routes/setup/schema.d.ts +61 -0
- package/dist/routes/setup/schema.d.ts.map +1 -0
- package/dist/routes/setup/schema.js +47 -0
- package/dist/routes/setup/schema.js.map +1 -0
- package/dist/routes/system/handlers.d.ts +63 -0
- package/dist/routes/system/handlers.d.ts.map +1 -0
- package/dist/routes/system/handlers.js +121 -0
- package/dist/routes/system/handlers.js.map +1 -0
- package/dist/routes/system/index.d.ts +34 -0
- package/dist/routes/system/index.d.ts.map +1 -0
- package/dist/routes/system/index.js +18 -0
- package/dist/routes/system/index.js.map +1 -0
- package/dist/routes/system/schema.d.ts +93 -0
- package/dist/routes/system/schema.d.ts.map +1 -0
- package/dist/routes/system/schema.js +109 -0
- package/dist/routes/system/schema.js.map +1 -0
- package/dist/routes/views/index.d.ts +21 -0
- package/dist/routes/views/index.d.ts.map +1 -0
- package/dist/routes/views/index.js +155 -0
- package/dist/routes/views/index.js.map +1 -0
- package/dist/routes/views/schema.d.ts +127 -0
- package/dist/routes/views/schema.d.ts.map +1 -0
- package/dist/routes/views/schema.js +56 -0
- package/dist/routes/views/schema.js.map +1 -0
- package/dist/routes/widget-data/index.d.ts +29 -0
- package/dist/routes/widget-data/index.d.ts.map +1 -0
- package/dist/routes/widget-data/index.js +152 -0
- package/dist/routes/widget-data/index.js.map +1 -0
- package/dist/routes/widget-data/schema.d.ts +252 -0
- package/dist/routes/widget-data/schema.d.ts.map +1 -0
- package/dist/routes/widget-data/schema.js +44 -0
- package/dist/routes/widget-data/schema.js.map +1 -0
- package/dist/setup/service.d.ts +63 -0
- package/dist/setup/service.d.ts.map +1 -0
- package/dist/setup/service.js +103 -0
- package/dist/setup/service.js.map +1 -0
- package/dist/start.d.ts +12 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +28 -0
- package/dist/start.js.map +1 -0
- package/dist/telemetry/payload.d.ts +66 -0
- package/dist/telemetry/payload.d.ts.map +1 -0
- package/dist/telemetry/payload.js +69 -0
- package/dist/telemetry/payload.js.map +1 -0
- package/dist/telemetry/service.d.ts +67 -0
- package/dist/telemetry/service.d.ts.map +1 -0
- package/dist/telemetry/service.js +103 -0
- package/dist/telemetry/service.js.map +1 -0
- package/dist/telemetry/update-check.d.ts +79 -0
- package/dist/telemetry/update-check.d.ts.map +1 -0
- package/dist/telemetry/update-check.js +103 -0
- package/dist/telemetry/update-check.js.map +1 -0
- package/dist/version.d.ts +14 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +21 -0
- package/dist/version.js.map +1 -0
- package/dist/widget-data/cache.d.ts +35 -0
- package/dist/widget-data/cache.d.ts.map +1 -0
- package/dist/widget-data/cache.js +67 -0
- package/dist/widget-data/cache.js.map +1 -0
- package/dist/widget-data/compiler.d.ts +107 -0
- package/dist/widget-data/compiler.d.ts.map +1 -0
- package/dist/widget-data/compiler.js +362 -0
- package/dist/widget-data/compiler.js.map +1 -0
- package/dist/widget-data/shapers.d.ts +75 -0
- package/dist/widget-data/shapers.d.ts.map +1 -0
- package/dist/widget-data/shapers.js +128 -0
- package/dist/widget-data/shapers.js.map +1 -0
- package/dist/widget-data/stream-publisher.d.ts +42 -0
- package/dist/widget-data/stream-publisher.d.ts.map +1 -0
- package/dist/widget-data/stream-publisher.js +34 -0
- package/dist/widget-data/stream-publisher.js.map +1 -0
- package/package.json +79 -0
- package/vocabulary/llm-allowlist.json +76 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared in-app notification writer (07-meta-store.md §3.20,
|
|
3
|
+
* 08-server-api.md §3 `notifications:<userId>`): every producer inserts
|
|
4
|
+
* through `notificationsRepo` and, when it has the hub, publishes the row on
|
|
5
|
+
* the recipient's channel so an open session's bell/badge updates without a
|
|
6
|
+
* refetch cycle.
|
|
7
|
+
*
|
|
8
|
+
* Channel-preference gating lives HERE, not in the repo: a producer names its
|
|
9
|
+
* `kind` (which doubles as the §3.21 `event_key`) and the writer consults
|
|
10
|
+
* `notificationPrefsRepo.channelsFor(...).inApp` — a user who switched the
|
|
11
|
+
* event off gets no row. Email/push channels are stored intent only in this
|
|
12
|
+
* build (no SMTP / no push transport); the prefs ROUTE explains that, per the
|
|
13
|
+
* never-hide-always-explain rule — the writer just ignores them.
|
|
14
|
+
*/
|
|
15
|
+
import { type CreateNotificationInput, type MetaDb, type Notification } from '@adminium/meta';
|
|
16
|
+
/** Event type published on `notifications:<userId>` for a fresh row. */
|
|
17
|
+
export declare const NOTIFICATION_CREATED_EVENT = "notification.created";
|
|
18
|
+
/** Event type published when rows flip to read (badge sync across tabs). */
|
|
19
|
+
export declare const NOTIFICATION_READ_EVENT = "notification.read";
|
|
20
|
+
/** The §3 channel name for one user's notification stream. */
|
|
21
|
+
export declare function notificationsChannel(userId: string): string;
|
|
22
|
+
/** The slice of RealtimeHub the writer needs (tests pass a recorder). */
|
|
23
|
+
export interface NotificationPublisher {
|
|
24
|
+
publish(channel: string, type: string, data: unknown): unknown;
|
|
25
|
+
}
|
|
26
|
+
export interface NotifyOptions {
|
|
27
|
+
/** When present, the row is fanned out on `notifications:<userId>`. */
|
|
28
|
+
hub?: NotificationPublisher | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Consult the user's §3.21 prefs for `kind` before inserting; default true.
|
|
31
|
+
* Producers of rows the user cannot opt out of (none today) pass false.
|
|
32
|
+
*/
|
|
33
|
+
respectPrefs?: boolean | undefined;
|
|
34
|
+
at?: number | undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Insert one notification (prefs permitting) and publish it. Returns the row,
|
|
38
|
+
* or `null` when the recipient has the event's in-app channel switched off.
|
|
39
|
+
* Best-effort belongs at the CALL SITE (backup/notify.ts precedent): a failed
|
|
40
|
+
* courtesy row must not fail the operation that succeeded.
|
|
41
|
+
*/
|
|
42
|
+
export declare function notify(meta: MetaDb, input: CreateNotificationInput, opts?: NotifyOptions): Promise<Notification | null>;
|
|
43
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/notifications/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAGL,KAAK,uBAAuB,EAC5B,KAAK,MAAM,EACX,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAC;AAExB,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAE3D,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAChE;AAED,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,GAAG,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,uBAAuB,EAC9B,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAU9B"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared in-app notification writer (07-meta-store.md §3.20,
|
|
3
|
+
* 08-server-api.md §3 `notifications:<userId>`): every producer inserts
|
|
4
|
+
* through `notificationsRepo` and, when it has the hub, publishes the row on
|
|
5
|
+
* the recipient's channel so an open session's bell/badge updates without a
|
|
6
|
+
* refetch cycle.
|
|
7
|
+
*
|
|
8
|
+
* Channel-preference gating lives HERE, not in the repo: a producer names its
|
|
9
|
+
* `kind` (which doubles as the §3.21 `event_key`) and the writer consults
|
|
10
|
+
* `notificationPrefsRepo.channelsFor(...).inApp` — a user who switched the
|
|
11
|
+
* event off gets no row. Email/push channels are stored intent only in this
|
|
12
|
+
* build (no SMTP / no push transport); the prefs ROUTE explains that, per the
|
|
13
|
+
* never-hide-always-explain rule — the writer just ignores them.
|
|
14
|
+
*/
|
|
15
|
+
import { notificationPrefsRepo, notificationsRepo, } from '@adminium/meta';
|
|
16
|
+
/** Event type published on `notifications:<userId>` for a fresh row. */
|
|
17
|
+
export const NOTIFICATION_CREATED_EVENT = 'notification.created';
|
|
18
|
+
/** Event type published when rows flip to read (badge sync across tabs). */
|
|
19
|
+
export const NOTIFICATION_READ_EVENT = 'notification.read';
|
|
20
|
+
/** The §3 channel name for one user's notification stream. */
|
|
21
|
+
export function notificationsChannel(userId) {
|
|
22
|
+
return `notifications:${userId}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Insert one notification (prefs permitting) and publish it. Returns the row,
|
|
26
|
+
* or `null` when the recipient has the event's in-app channel switched off.
|
|
27
|
+
* Best-effort belongs at the CALL SITE (backup/notify.ts precedent): a failed
|
|
28
|
+
* courtesy row must not fail the operation that succeeded.
|
|
29
|
+
*/
|
|
30
|
+
export async function notify(meta, input, opts = {}) {
|
|
31
|
+
if (opts.respectPrefs ?? true) {
|
|
32
|
+
const channels = await notificationPrefsRepo(meta).channelsFor(input.userId, input.kind);
|
|
33
|
+
if (!channels.inApp)
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const row = await notificationsRepo(meta).create(input, opts.at);
|
|
37
|
+
opts.hub?.publish(notificationsChannel(row.userId), NOTIFICATION_CREATED_EVENT, {
|
|
38
|
+
notification: row,
|
|
39
|
+
});
|
|
40
|
+
return row;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/notifications/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EACL,qBAAqB,EACrB,iBAAiB,GAIlB,MAAM,gBAAgB,CAAC;AAExB,wEAAwE;AACxE,MAAM,CAAC,MAAM,0BAA0B,GAAG,sBAAsB,CAAC;AACjE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,uBAAuB,GAAG,mBAAmB,CAAC;AAE3D,8DAA8D;AAC9D,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,iBAAiB,MAAM,EAAE,CAAC;AACnC,CAAC;AAkBD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAY,EACZ,KAA8B,EAC9B,OAAsB,EAAE;IAExB,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzF,IAAI,CAAC,QAAQ,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;IACnC,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,0BAA0B,EAAE;QAC9E,YAAY,EAAE,GAAG;KAClB,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type ApiKey, type MetaDb, type Session, type User } from '@adminium/meta';
|
|
2
|
+
import type { Env } from '../config/env.js';
|
|
3
|
+
/** Payload handed to the reset-delivery hook (email transport lands later). */
|
|
4
|
+
export interface PasswordResetDelivery {
|
|
5
|
+
userId: string;
|
|
6
|
+
email: string;
|
|
7
|
+
/** Plaintext single-use token — never stored, never logged. */
|
|
8
|
+
token: string;
|
|
9
|
+
expiresAt: number;
|
|
10
|
+
}
|
|
11
|
+
export interface AuthContext {
|
|
12
|
+
meta: MetaDb;
|
|
13
|
+
env: Env;
|
|
14
|
+
/** HKDF-derived AES key for TOTP secrets at rest. */
|
|
15
|
+
totpKey: Buffer;
|
|
16
|
+
/** Test/email hook: receives plaintext reset tokens on `password/forgot`. */
|
|
17
|
+
deliverResetToken: ((delivery: PasswordResetDelivery) => void) | undefined;
|
|
18
|
+
}
|
|
19
|
+
export interface AuthPluginOptions {
|
|
20
|
+
env: Env;
|
|
21
|
+
metaDb?: MetaDb | null | undefined;
|
|
22
|
+
deliverResetToken?: ((delivery: PasswordResetDelivery) => void) | undefined;
|
|
23
|
+
}
|
|
24
|
+
declare module 'fastify' {
|
|
25
|
+
interface FastifyRequest {
|
|
26
|
+
/** Active-session user; `null` for anonymous or API-key principals. */
|
|
27
|
+
user: User | null;
|
|
28
|
+
/** The resolved live session row backing `user`. */
|
|
29
|
+
session: Session | null;
|
|
30
|
+
/** API-key principal (bearer) — RBAC wiring is the rbac plugin's. */
|
|
31
|
+
apiKey: ApiKey | null;
|
|
32
|
+
/** True when a session token was presented but timed out (§1.4). */
|
|
33
|
+
sessionExpired: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface FastifyInstance {
|
|
36
|
+
authContext: AuthContext | null;
|
|
37
|
+
requireMeta: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
38
|
+
requireAuth: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export declare const authPlugin: import("fastify").FastifyPluginCallback<AuthPluginOptions, import("fastify").RawServerDefault, import("fastify").FastifyTypeProviderDefault, import("fastify").FastifyBaseLogger>;
|
|
42
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/plugins/auth.ts"],"names":[],"mappings":"AAeA,OAAO,EAIL,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,IAAI,EACV,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAS5C,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,iBAAiB,EAAE,CAAC,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC5E;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,iBAAiB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC7E;AAKD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,uEAAuE;QACvE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;QAClB,oDAAoD;QACpD,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;QACxB,qEAAqE;QACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,oEAAoE;QACpE,cAAc,EAAE,OAAO,CAAC;KACzB;IACD,UAAU,eAAe;QACvB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;QAChC,WAAW,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7E,WAAW,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9E;CACF;AAED,eAAO,MAAM,UAAU,mLA0EtB,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `auth` plugin (08-server-api.md §1.2, §2.1): resolves the signed
|
|
3
|
+
* `adminium_session` cookie (or an `Authorization: Bearer adm_…` API key —
|
|
4
|
+
* stub for the key-management routes) to a principal on every request and
|
|
5
|
+
* decorates `request.user` / `request.session` / `request.apiKey`.
|
|
6
|
+
*
|
|
7
|
+
* Exposes:
|
|
8
|
+
* - `app.authContext` — meta handle + derived keys + delivery hooks, `null`
|
|
9
|
+
* when the server boots without a meta DB (wave-1 compatible);
|
|
10
|
+
* - `app.requireMeta` — preHandler: 503 META_NOT_CONFIGURED without meta;
|
|
11
|
+
* - `app.requireAuth` — preHandler: 401 UNAUTHENTICATED (no/invalid/revoked
|
|
12
|
+
* token) or 401 SESSION_EXPIRED (session existed but idle/absolute timed out).
|
|
13
|
+
*/
|
|
14
|
+
import fp from 'fastify-plugin';
|
|
15
|
+
import { apiKeysRepo, sessionsRepo, usersRepo, } from '@adminium/meta';
|
|
16
|
+
import { AppError, UnauthorizedError } from '../errors.js';
|
|
17
|
+
import { hashToken, readSessionCookie, resolveSessionByToken, } from '../auth/sessions.js';
|
|
18
|
+
import { totpEncryptionKey } from '../auth/totp.js';
|
|
19
|
+
/** API keys are Stripe-style `adm_…` bearer tokens (07-meta-store.md §3.7). */
|
|
20
|
+
const API_KEY_PREFIX = 'adm_';
|
|
21
|
+
export const authPlugin = fp(async (app, opts) => {
|
|
22
|
+
const meta = opts.metaDb ?? null;
|
|
23
|
+
const context = meta === null
|
|
24
|
+
? null
|
|
25
|
+
: {
|
|
26
|
+
meta,
|
|
27
|
+
env: opts.env,
|
|
28
|
+
totpKey: totpEncryptionKey(opts.env.ADMINIUM_SECRET),
|
|
29
|
+
deliverResetToken: opts.deliverResetToken,
|
|
30
|
+
};
|
|
31
|
+
app.decorate('authContext', context);
|
|
32
|
+
app.decorateRequest('user', null);
|
|
33
|
+
app.decorateRequest('session', null);
|
|
34
|
+
app.decorateRequest('apiKey', null);
|
|
35
|
+
app.decorateRequest('sessionExpired', false);
|
|
36
|
+
app.decorate('requireMeta', async () => {
|
|
37
|
+
if (context === null) {
|
|
38
|
+
throw new AppError(503, 'META_NOT_CONFIGURED', 'No meta store is configured — authentication is unavailable.');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
app.decorate('requireAuth', async (request) => {
|
|
42
|
+
if (request.user !== null && request.session !== null)
|
|
43
|
+
return;
|
|
44
|
+
if (request.sessionExpired)
|
|
45
|
+
throw new UnauthorizedError('SESSION_EXPIRED');
|
|
46
|
+
throw new UnauthorizedError('UNAUTHENTICATED');
|
|
47
|
+
});
|
|
48
|
+
if (context === null)
|
|
49
|
+
return;
|
|
50
|
+
app.addHook('onRequest', async (request) => {
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
// API-key bearer stub (§8): resolves the principal; RBAC comes later.
|
|
53
|
+
const authorization = request.headers.authorization;
|
|
54
|
+
if (typeof authorization === 'string' && authorization.startsWith('Bearer ')) {
|
|
55
|
+
const bearer = authorization.slice('Bearer '.length).trim();
|
|
56
|
+
if (bearer.startsWith(API_KEY_PREFIX)) {
|
|
57
|
+
const key = await apiKeysRepo(context.meta).findValidByTokenHash(hashToken(bearer), now);
|
|
58
|
+
if (key !== null) {
|
|
59
|
+
request.apiKey = key;
|
|
60
|
+
await apiKeysRepo(context.meta).touchLastUsed(key.id, now);
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const token = readSessionCookie(request);
|
|
66
|
+
if (token === null)
|
|
67
|
+
return;
|
|
68
|
+
const resolution = await resolveSessionByToken(context.meta, token, now);
|
|
69
|
+
if (resolution.state === 'expired') {
|
|
70
|
+
request.sessionExpired = true;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (resolution.state !== 'active')
|
|
74
|
+
return;
|
|
75
|
+
const user = await usersRepo(context.meta).findById(resolution.session.userId);
|
|
76
|
+
if (user === null || user.status !== 'active')
|
|
77
|
+
return;
|
|
78
|
+
request.user = user;
|
|
79
|
+
request.session = resolution.session;
|
|
80
|
+
// Sliding idle window: throttled to one write per minute by the repo.
|
|
81
|
+
await sessionsRepo(context.meta).touch(resolution.session.id, now);
|
|
82
|
+
});
|
|
83
|
+
}, { name: 'adminium-auth', fastify: '5.x', dependencies: ['adminium-core'] });
|
|
84
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/plugins/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Env } from '../config/env.js';
|
|
2
|
+
/** One §6 bucket: a fixed window of `max` requests per `timeWindowMs`. */
|
|
3
|
+
export interface RateBucket {
|
|
4
|
+
max: number;
|
|
5
|
+
timeWindowMs: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The §6 bucket table (08-server-api.md §6). Keys are the
|
|
9
|
+
* `config.rateLimitBucket` markers routes declare; a route declaring a bucket
|
|
10
|
+
* that is not in this table fails AT BOOT (the onRoute hook throws), so the
|
|
11
|
+
* two spellings cannot drift apart silently.
|
|
12
|
+
*
|
|
13
|
+
* - `auth-login` — `/auth/login`, `/auth/2fa/verify`, `/setup/super-admin`,
|
|
14
|
+
* `/auth/desktop-session` (5/min, §6 row 1; §7 item 7
|
|
15
|
+
* "TOTP … verify rate-limited").
|
|
16
|
+
* - `auth-password-forgot` — `/auth/password/forgot` (3/hour, §6 row 2).
|
|
17
|
+
* - `auth-password-reset` — `/auth/password/reset`: the token CONSUME side.
|
|
18
|
+
* Not in the §6 table by name, but §7 item 7's
|
|
19
|
+
* single-use + 30-min-TTL reset tokens are only as
|
|
20
|
+
* strong as the guess rate this cap sets.
|
|
21
|
+
* - `search` — `GET /search` (60/min, §6 row 5): each request fans
|
|
22
|
+
* out parallel ILIKE queries over up to 20 tables, the
|
|
23
|
+
* cheapest DoS lever of the unbucketed routes.
|
|
24
|
+
*
|
|
25
|
+
* DELIBERATE §6 DEVIATIONS (documented here so the table can't drift
|
|
26
|
+
* silently):
|
|
27
|
+
* - The auth buckets key per-IP, not the spec'd "IP + email": per-IP keying
|
|
28
|
+
* is what guarantees a LAN flood can never lock the loopback
|
|
29
|
+
* `/auth/desktop-session` exchange out (tested in rate-limit.test.ts). A
|
|
30
|
+
* per-account counter for distributed credential sprays is a possible
|
|
31
|
+
* additive follow-up, not a replacement.
|
|
32
|
+
* - The remaining §6 rows (General API 300/min, widget-data 120/min,
|
|
33
|
+
* exports/imports 10/h, LLM 20/h, files 30/h) and the
|
|
34
|
+
* `adminium_settings.security` override are a tracked pre-v1 hardening
|
|
35
|
+
* follow-up — they need principal-resolution (session-keyed) buckets,
|
|
36
|
+
* which this per-IP fixed-window store does not provide yet.
|
|
37
|
+
*/
|
|
38
|
+
export declare const RATE_BUCKETS: Readonly<Record<string, RateBucket>>;
|
|
39
|
+
export interface CorePluginOptions {
|
|
40
|
+
env: Env;
|
|
41
|
+
/**
|
|
42
|
+
* The dashboard build directory `app.ts` hands the static plugin — read here
|
|
43
|
+
* (never served) to compute the CSP inline-script hash allowance.
|
|
44
|
+
*/
|
|
45
|
+
staticRoot?: string | undefined;
|
|
46
|
+
}
|
|
47
|
+
export declare const corePlugin: import("fastify").FastifyPluginCallback<CorePluginOptions, import("fastify").RawServerDefault, import("fastify").FastifyTypeProviderDefault, import("fastify").FastifyBaseLogger>;
|
|
48
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"AA+DA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAG5C,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAK7D,CAAC;AA2EF,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,GAAG,CAAC;IACT;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,eAAO,MAAM,UAAU,mLA+FtB,CAAC"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `core` plugin (08-server-api.md §1.2): cookie support (signed with
|
|
3
|
+
* ADMINIUM_SECRET), the same-origin CORS default — no CORS headers are emitted
|
|
4
|
+
* unless ADMINIUM_CORS_ORIGINS opts specific origins in (§7 item 4) — plus the
|
|
5
|
+
* §7-item-5 security headers (@fastify/helmet) and the §6 rate limiter
|
|
6
|
+
* (@fastify/rate-limit). Request-id, redaction, and the error envelope live in
|
|
7
|
+
* `app.ts` because they attach at instance creation.
|
|
8
|
+
*
|
|
9
|
+
* ─── Rate limiting (§6) ───────────────────────────────────────────────────────
|
|
10
|
+
*
|
|
11
|
+
* The limiter is registered `global: false` and enabled per route by the
|
|
12
|
+
* `config.rateLimitBucket` markers the credential-facing routes already carry
|
|
13
|
+
* (routes/auth, routes/setup, routes/auth/desktop-session). An `onRoute` hook
|
|
14
|
+
* added HERE, before @fastify/rate-limit registers its own, translates each
|
|
15
|
+
* marker into the plugin's per-route `config.rateLimit` — so a route declares
|
|
16
|
+
* WHICH bucket it is in and this table stays the single owner of the limits
|
|
17
|
+
* (08 §6: "Limits are constants in `apps/server/src/plugins/core.ts`
|
|
18
|
+
* (`RATE_BUCKETS`)"; the `adminium_settings.security` override is a later
|
|
19
|
+
* wave — core composes before any meta store exists).
|
|
20
|
+
*
|
|
21
|
+
* Buckets are FIXED-WINDOW counters in one shared in-memory map (§6: "the
|
|
22
|
+
* in-memory store — single-process: droplet, self-host, and Electron all run
|
|
23
|
+
* one instance"). The store is shared across ROUTES, not just requests, and
|
|
24
|
+
* keys are `<bucket>:<ip>`: `/auth/login`, `/auth/2fa/verify`,
|
|
25
|
+
* `/setup/super-admin` and `/auth/desktop-session` all draw down the same five
|
|
26
|
+
* tries per minute per address — per-route counters would hand an attacker one
|
|
27
|
+
* budget per door. Keying by ip (not ip+session) because every bucketed route
|
|
28
|
+
* is unauthenticated by nature; it also means a LAN peer hammering
|
|
29
|
+
* `/auth/desktop-session` (11-electron.md §8.3) can never lock the loopback
|
|
30
|
+
* exchange out.
|
|
31
|
+
*
|
|
32
|
+
* A limit hit throws the SAME `RateLimitedError` handlers would throw, so the
|
|
33
|
+
* 429 rides the one §1.4 envelope (`details: { bucket, limit, resetAt }`) and
|
|
34
|
+
* the plugin's own `retry-after` / `x-ratelimit-*` headers survive on the
|
|
35
|
+
* reply the global error handler sends.
|
|
36
|
+
*
|
|
37
|
+
* ─── Security headers (§7 item 5) ─────────────────────────────────────────────
|
|
38
|
+
*
|
|
39
|
+
* CSP is `default-src 'self'` with exactly one script allowance: sha256 hashes
|
|
40
|
+
* of the inline scripts in the SERVED dashboard `index.html` — in practice the
|
|
41
|
+
* theme pre-hydration flash guard (02-design-system.md §4.3), hashed from the
|
|
42
|
+
* build at boot so the allowance tracks the artifact rather than a constant
|
|
43
|
+
* that can drift. No `upgrade-insecure-requests` and no HSTS unless
|
|
44
|
+
* `ADMINIUM_TRUST_PROXY` (behind Caddy/TLS): the desktop shell and §8.3 LAN
|
|
45
|
+
* share serve plain `http://` loopback/LAN origins by design, and either
|
|
46
|
+
* directive would quietly break them. `connect-src` adds `ws://<host>
|
|
47
|
+
* wss://<host>` derived from each request's Host header, because CSP's
|
|
48
|
+
* `'self'` does not reliably cover same-host WebSocket upgrades (`/ws`, §4)
|
|
49
|
+
* across engines — but bare `ws:`/`wss:` scheme sources would allow a socket
|
|
50
|
+
* to ANY origin, which defeats the exfiltration boundary `'self'` sets.
|
|
51
|
+
*/
|
|
52
|
+
import { createHash } from 'node:crypto';
|
|
53
|
+
import { readFile } from 'node:fs/promises';
|
|
54
|
+
import { join, resolve } from 'node:path';
|
|
55
|
+
import fastifyCookie from '@fastify/cookie';
|
|
56
|
+
import fastifyCors from '@fastify/cors';
|
|
57
|
+
import fastifyHelmet from '@fastify/helmet';
|
|
58
|
+
import fastifyRateLimit from '@fastify/rate-limit';
|
|
59
|
+
import fp from 'fastify-plugin';
|
|
60
|
+
import { RateLimitedError } from '../errors.js';
|
|
61
|
+
/**
|
|
62
|
+
* The §6 bucket table (08-server-api.md §6). Keys are the
|
|
63
|
+
* `config.rateLimitBucket` markers routes declare; a route declaring a bucket
|
|
64
|
+
* that is not in this table fails AT BOOT (the onRoute hook throws), so the
|
|
65
|
+
* two spellings cannot drift apart silently.
|
|
66
|
+
*
|
|
67
|
+
* - `auth-login` — `/auth/login`, `/auth/2fa/verify`, `/setup/super-admin`,
|
|
68
|
+
* `/auth/desktop-session` (5/min, §6 row 1; §7 item 7
|
|
69
|
+
* "TOTP … verify rate-limited").
|
|
70
|
+
* - `auth-password-forgot` — `/auth/password/forgot` (3/hour, §6 row 2).
|
|
71
|
+
* - `auth-password-reset` — `/auth/password/reset`: the token CONSUME side.
|
|
72
|
+
* Not in the §6 table by name, but §7 item 7's
|
|
73
|
+
* single-use + 30-min-TTL reset tokens are only as
|
|
74
|
+
* strong as the guess rate this cap sets.
|
|
75
|
+
* - `search` — `GET /search` (60/min, §6 row 5): each request fans
|
|
76
|
+
* out parallel ILIKE queries over up to 20 tables, the
|
|
77
|
+
* cheapest DoS lever of the unbucketed routes.
|
|
78
|
+
*
|
|
79
|
+
* DELIBERATE §6 DEVIATIONS (documented here so the table can't drift
|
|
80
|
+
* silently):
|
|
81
|
+
* - The auth buckets key per-IP, not the spec'd "IP + email": per-IP keying
|
|
82
|
+
* is what guarantees a LAN flood can never lock the loopback
|
|
83
|
+
* `/auth/desktop-session` exchange out (tested in rate-limit.test.ts). A
|
|
84
|
+
* per-account counter for distributed credential sprays is a possible
|
|
85
|
+
* additive follow-up, not a replacement.
|
|
86
|
+
* - The remaining §6 rows (General API 300/min, widget-data 120/min,
|
|
87
|
+
* exports/imports 10/h, LLM 20/h, files 30/h) and the
|
|
88
|
+
* `adminium_settings.security` override are a tracked pre-v1 hardening
|
|
89
|
+
* follow-up — they need principal-resolution (session-keyed) buckets,
|
|
90
|
+
* which this per-IP fixed-window store does not provide yet.
|
|
91
|
+
*/
|
|
92
|
+
export const RATE_BUCKETS = {
|
|
93
|
+
'auth-login': { max: 5, timeWindowMs: 60_000 },
|
|
94
|
+
'auth-password-forgot': { max: 3, timeWindowMs: 3_600_000 },
|
|
95
|
+
'auth-password-reset': { max: 5, timeWindowMs: 60_000 },
|
|
96
|
+
search: { max: 60, timeWindowMs: 60_000 },
|
|
97
|
+
};
|
|
98
|
+
/** Expired-entry sweep trigger — keeps the map bounded under key churn. */
|
|
99
|
+
const SWEEP_SIZE = 5_000;
|
|
100
|
+
/**
|
|
101
|
+
* The §6 in-memory store, as a @fastify/rate-limit custom-store class whose
|
|
102
|
+
* instances (the per-route `child()`ren the plugin creates) all share ONE
|
|
103
|
+
* `Map` captured per server instance. Sharing is the point — see the module
|
|
104
|
+
* header — and is safe because keys embed the bucket name, so two buckets
|
|
105
|
+
* can never collide even though they share the map. Fixed-window: the first
|
|
106
|
+
* hit opens a window of the route's `timeWindow`, and the counter resets when
|
|
107
|
+
* it lapses (`incr` receives the window per call, per the store contract).
|
|
108
|
+
*/
|
|
109
|
+
function createBucketStoreClass() {
|
|
110
|
+
const hits = new Map();
|
|
111
|
+
return class BucketStore {
|
|
112
|
+
incr(key, callback, timeWindow) {
|
|
113
|
+
const now = Date.now();
|
|
114
|
+
if (hits.size >= SWEEP_SIZE) {
|
|
115
|
+
for (const [staleKey, hit] of hits) {
|
|
116
|
+
if (hit.resetAt <= now)
|
|
117
|
+
hits.delete(staleKey);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
let hit = hits.get(key);
|
|
121
|
+
if (hit === undefined || hit.resetAt <= now) {
|
|
122
|
+
hit = { current: 0, resetAt: now + timeWindow };
|
|
123
|
+
hits.set(key, hit);
|
|
124
|
+
}
|
|
125
|
+
hit.current += 1;
|
|
126
|
+
callback(null, { current: hit.current, ttl: hit.resetAt - now });
|
|
127
|
+
}
|
|
128
|
+
child() {
|
|
129
|
+
return new BucketStore();
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/** Matches inline `<script>` blocks (no `src=`) in the dashboard index.html. */
|
|
134
|
+
const INLINE_SCRIPT_PATTERN = /<script(?![^>]*\bsrc\s*=)[^>]*>([\s\S]*?)<\/script>/gi;
|
|
135
|
+
/**
|
|
136
|
+
* CSP `'sha256-…'` allowances for the inline scripts the served SPA actually
|
|
137
|
+
* carries. Read from the same `index.html` the static plugin will serve, so a
|
|
138
|
+
* rebuilt pre-hydration script never turns into a white screen behind a stale
|
|
139
|
+
* hash. Absent or unreadable build ⇒ no allowances (API-only boot).
|
|
140
|
+
*/
|
|
141
|
+
async function inlineScriptHashes(staticRoot) {
|
|
142
|
+
if (staticRoot === undefined || staticRoot === '')
|
|
143
|
+
return [];
|
|
144
|
+
let html;
|
|
145
|
+
try {
|
|
146
|
+
html = await readFile(join(resolve(staticRoot), 'index.html'), 'utf8');
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
const hashes = [];
|
|
152
|
+
for (const match of html.matchAll(INLINE_SCRIPT_PATTERN)) {
|
|
153
|
+
const body = match[1] ?? '';
|
|
154
|
+
if (body.trim() === '')
|
|
155
|
+
continue;
|
|
156
|
+
// CSP hashes cover the EXACT bytes between the tags — no trimming.
|
|
157
|
+
hashes.push(`'sha256-${createHash('sha256').update(body, 'utf8').digest('base64')}'`);
|
|
158
|
+
}
|
|
159
|
+
return hashes;
|
|
160
|
+
}
|
|
161
|
+
export const corePlugin = fp(async (app, { env, staticRoot }) => {
|
|
162
|
+
await app.register(fastifyCookie, {
|
|
163
|
+
secret: env.ADMINIUM_SECRET,
|
|
164
|
+
hook: 'onRequest',
|
|
165
|
+
});
|
|
166
|
+
const origins = env.ADMINIUM_CORS_ORIGINS;
|
|
167
|
+
if (origins !== undefined && origins.length > 0) {
|
|
168
|
+
await app.register(fastifyCors, {
|
|
169
|
+
origin: [...origins],
|
|
170
|
+
credentials: true,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// §7 item 5. Helmet's hook is global, so API replies, static assets and
|
|
174
|
+
// the SPA fallback all carry the same headers.
|
|
175
|
+
await app.register(fastifyHelmet, {
|
|
176
|
+
contentSecurityPolicy: {
|
|
177
|
+
useDefaults: false,
|
|
178
|
+
directives: {
|
|
179
|
+
'default-src': ["'self'"],
|
|
180
|
+
'base-uri': ["'self'"],
|
|
181
|
+
'object-src': ["'none'"],
|
|
182
|
+
'frame-ancestors': ["'none'"],
|
|
183
|
+
'form-action': ["'self'"],
|
|
184
|
+
'script-src': ["'self'", ...(await inlineScriptHashes(staticRoot))],
|
|
185
|
+
// Runtime style injection (chart/table libraries set style attrs).
|
|
186
|
+
'style-src': ["'self'", "'unsafe-inline'"],
|
|
187
|
+
// The map widgets' basemap tiles load from the Carto CDN
|
|
188
|
+
// (packages/widgets geo-lib.ts CARTO_TILES) — without this
|
|
189
|
+
// allowance every deployed MapBubble renders over a blank basemap.
|
|
190
|
+
'img-src': ["'self'", 'data:', 'blob:', 'https://*.basemaps.cartocdn.com'],
|
|
191
|
+
'font-src': ["'self'", 'data:'],
|
|
192
|
+
// Same-HOST WebSocket only. Bare `ws:`/`wss:` scheme sources would
|
|
193
|
+
// authorize a socket to ANY origin — an XSS foothold could
|
|
194
|
+
// exfiltrate through `new WebSocket('wss://attacker/…')` — so the
|
|
195
|
+
// allowance is derived per request from the Host header the page
|
|
196
|
+
// itself was served on (loopback, LAN ip, or proxied domain alike).
|
|
197
|
+
'connect-src': [
|
|
198
|
+
"'self'",
|
|
199
|
+
(req) => {
|
|
200
|
+
const host = req.headers.host;
|
|
201
|
+
return host === undefined || host === ''
|
|
202
|
+
? "'self'"
|
|
203
|
+
: `ws://${host} wss://${host}`;
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
'worker-src': ["'self'", 'blob:'],
|
|
207
|
+
'manifest-src': ["'self'"],
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
// frame-ancestors 'none' is the modern half; X-Frame-Options must agree.
|
|
211
|
+
frameguard: { action: 'deny' },
|
|
212
|
+
// HSTS only behind TLS (§7 item 5); on the desktop shell's loopback and
|
|
213
|
+
// §8.3's LAN origins it would pin browsers to an https that isn't there.
|
|
214
|
+
...(env.ADMINIUM_TRUST_PROXY ? {} : { hsts: false }),
|
|
215
|
+
});
|
|
216
|
+
// §6 marker translation. Added BEFORE @fastify/rate-limit registers so its
|
|
217
|
+
// own onRoute hook (which reads `config.rateLimit`) runs after this one.
|
|
218
|
+
app.addHook('onRoute', (route) => {
|
|
219
|
+
const bucket = route.config?.rateLimitBucket;
|
|
220
|
+
if (bucket === undefined)
|
|
221
|
+
return;
|
|
222
|
+
const spec = RATE_BUCKETS[bucket];
|
|
223
|
+
if (spec === undefined) {
|
|
224
|
+
const methods = Array.isArray(route.method) ? route.method.join(',') : route.method;
|
|
225
|
+
throw new Error(`route ${methods} ${route.url} declares unknown rate-limit bucket "${bucket}" — add it to RATE_BUCKETS (plugins/core.ts, 08-server-api.md §6)`);
|
|
226
|
+
}
|
|
227
|
+
route.config = {
|
|
228
|
+
...route.config,
|
|
229
|
+
rateLimit: {
|
|
230
|
+
max: spec.max,
|
|
231
|
+
timeWindow: spec.timeWindowMs,
|
|
232
|
+
keyGenerator: (request) => `${bucket}:${request.ip}`,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
await app.register(fastifyRateLimit, {
|
|
237
|
+
global: false,
|
|
238
|
+
store: createBucketStoreClass(),
|
|
239
|
+
// Thrown by the plugin, serialized by the global §1.4 error handler; the
|
|
240
|
+
// plugin has already set `retry-after` + `x-ratelimit-*` on the reply.
|
|
241
|
+
errorResponseBuilder: (request, context) => new RateLimitedError(`Too many requests. Try again in ${context.after}.`, {
|
|
242
|
+
bucket: request.routeOptions.config?.rateLimitBucket ?? 'unknown',
|
|
243
|
+
limit: context.max,
|
|
244
|
+
resetAt: new Date(Date.now() + context.ttl).toISOString(),
|
|
245
|
+
}),
|
|
246
|
+
});
|
|
247
|
+
}, { name: 'adminium-core', fastify: '5.x' });
|
|
248
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `rbac` plugin (08-server-api.md §5, M2-T05): decorates
|
|
3
|
+
*
|
|
4
|
+
* - `request.can(permission)` — lazy, per-request-cached allow/deny against
|
|
5
|
+
* the resolved permission set (union of role grants; super-admin bypass;
|
|
6
|
+
* deny-by-default),
|
|
7
|
+
* - `app.rbac.require(permission)` — route `preHandler` that throws
|
|
8
|
+
* `ForbiddenError` with the missing permission in `details` and writes an
|
|
9
|
+
* `rbac`-category `permission.denied` audit entry,
|
|
10
|
+
* - `app.rbac.audit(request, entry)` — actor/ip/ua/request-id-stamped audit
|
|
11
|
+
* append for the mutating routes in this wave,
|
|
12
|
+
* - the API-key request-auth path: `Authorization: Bearer adm_sk_…` →
|
|
13
|
+
* hashed lookup → `request.apiKeyPrincipal` acting with the key's role
|
|
14
|
+
* (§2.16), with a throttled `last_used_at` touch.
|
|
15
|
+
*
|
|
16
|
+
* Session users arrive as `request.user` from `plugins/auth.ts`; this plugin
|
|
17
|
+
* only *reads* that decoration (structurally — see rbac/principal.ts).
|
|
18
|
+
*/
|
|
19
|
+
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
20
|
+
import { type AuditEntryInput, type MetaDb } from '@adminium/meta';
|
|
21
|
+
import { type ApiKeyPrincipal } from '../rbac/principal.js';
|
|
22
|
+
import { type PermissionSet } from '../rbac/resolver.js';
|
|
23
|
+
/** Audit fields the caller provides; actor/ip/ua/request-id come from the request. */
|
|
24
|
+
export type RequestAuditInput = Omit<AuditEntryInput, 'actorKind' | 'actorId' | 'actorLabel' | 'ip' | 'userAgent' | 'requestId'>;
|
|
25
|
+
export interface RbacDecoration {
|
|
26
|
+
meta: MetaDb;
|
|
27
|
+
/** Route guard: 401 without a principal, 403 (+ audit) without the grant. */
|
|
28
|
+
require(permission: string): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
29
|
+
/** Resolve (and per-request cache) the acting principal's permission set. */
|
|
30
|
+
resolve(request: FastifyRequest): Promise<PermissionSet>;
|
|
31
|
+
/** Append an audit entry stamped with the request's actor + transport info. */
|
|
32
|
+
audit(request: FastifyRequest, entry: RequestAuditInput): Promise<void>;
|
|
33
|
+
now(): number;
|
|
34
|
+
}
|
|
35
|
+
declare module 'fastify' {
|
|
36
|
+
interface FastifyInstance {
|
|
37
|
+
rbac: RbacDecoration;
|
|
38
|
+
}
|
|
39
|
+
interface FastifyRequest {
|
|
40
|
+
/** Set by the rbac plugin when a valid `adm_sk_…` bearer key is presented. */
|
|
41
|
+
apiKeyPrincipal: ApiKeyPrincipal | null;
|
|
42
|
+
/** Allow/deny check against the resolved permission set (cached per request). */
|
|
43
|
+
can(permission: string): Promise<boolean>;
|
|
44
|
+
/** @internal per-request resolution cache — use `request.can()` instead. */
|
|
45
|
+
rbacResolution: PermissionSet | null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export interface RbacPluginOptions {
|
|
49
|
+
meta: MetaDb;
|
|
50
|
+
/** Injectable clock (tests: last-used throttling, key expiry). */
|
|
51
|
+
now?: () => number;
|
|
52
|
+
}
|
|
53
|
+
export declare const rbacPlugin: import("fastify").FastifyPluginCallback<RbacPluginOptions, import("fastify").RawServerDefault, import("fastify").FastifyTypeProviderDefault, import("fastify").FastifyBaseLogger>;
|
|
54
|
+
//# sourceMappingURL=rbac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac.d.ts","sourceRoot":"","sources":["../../src/plugins/rbac.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE5D,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,MAAM,EACZ,MAAM,gBAAgB,CAAC;AASxB,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAE7B,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,eAAe,EACf,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,GAAG,WAAW,GAAG,WAAW,CAC1E,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7F,6EAA6E;IAC7E,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACzD,+EAA+E;IAC/E,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,GAAG,IAAI,MAAM,CAAC;CACf;AAED,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,eAAe;QACvB,IAAI,EAAE,cAAc,CAAC;KACtB;IACD,UAAU,cAAc;QACtB,8EAA8E;QAC9E,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;QACxC,iFAAiF;QACjF,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC1C,4EAA4E;QAC5E,cAAc,EAAE,aAAa,GAAG,IAAI,CAAC;KACtC;CACF;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,mLAqFtB,CAAC"}
|