@corbet-labs/ccht 0.1.0 → 0.2.2
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/README.md +199 -168
- package/index.d.ts +17 -2
- package/index.js +8 -1
- package/package.json +12 -26
- package/src/auth.ts +149 -0
- package/src/components/AccountConnection.svelte +201 -0
- package/src/components/Dock.svelte +172 -0
- package/src/dock.ts +244 -0
- package/wasm/ccht_bg.wasm +0 -0
- package/LICENSE +0 -307
- package/LICENSE.md +0 -25
- package/LICENSES/GPL-3.0-only.txt +0 -232
- package/LICENSES/LGPL-3.0-only.txt +0 -304
- package/LICENSES/dependencies/agent-client-protocol-2.1.0/LICENSE +0 -191
- package/LICENSES/dependencies/agent-client-protocol-derive-2.1.0/LICENSE +0 -191
- package/LICENSES/dependencies/agent-client-protocol-schema-1.7.0/LICENSE +0 -190
- package/LICENSES/dependencies/android_system_properties-0.1.6/LICENSE-APACHE +0 -13
- package/LICENSES/dependencies/android_system_properties-0.1.6/LICENSE-MIT +0 -20
- package/LICENSES/dependencies/anyhow-1.0.104/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/anyhow-1.0.104/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-channel-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-channel-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-io-2.6.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-io-2.6.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-lock-3.4.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-lock-3.4.2/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-process-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-process-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-signal-0.2.14/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-signal-0.2.14/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/async-task-4.7.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/async-task-4.7.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/atomic-waker-1.1.2/LICENSE-THIRD-PARTY +0 -45
- package/LICENSES/dependencies/autocfg-1.5.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/autocfg-1.5.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/base64-0.22.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/base64-0.22.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/base64-0.23.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/base64-0.23.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/bitflags-1.3.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bitflags-1.3.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/bitflags-2.13.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bitflags-2.13.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/blocking-1.7.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/blocking-1.7.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/bs58-0.5.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bs58-0.5.1/LICENSE-MIT +0 -20
- package/LICENSES/dependencies/bumpalo-3.20.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/bumpalo-3.20.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/cc-1.4.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/cc-1.4.5/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/cfg-if-1.0.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/cfg-if-1.0.4/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/chrono-0.4.45/LICENSE.txt +0 -240
- package/LICENSES/dependencies/concurrent-queue-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/concurrent-queue-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/convert_case-0.10.0/LICENSE +0 -21
- package/LICENSES/dependencies/core-foundation-sys-0.8.7/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/core-foundation-sys-0.8.7/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/crossbeam-deque-0.8.8/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/crossbeam-deque-0.8.8/LICENSE-MIT +0 -27
- package/LICENSES/dependencies/crossbeam-epoch-0.9.21/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/crossbeam-epoch-0.9.21/LICENSE-MIT +0 -27
- package/LICENSES/dependencies/crossbeam-utils-0.8.23/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/crossbeam-utils-0.8.23/LICENSE-MIT +0 -27
- package/LICENSES/dependencies/darling-0.24.1/LICENSE +0 -21
- package/LICENSES/dependencies/darling_core-0.24.1/LICENSE +0 -21
- package/LICENSES/dependencies/darling_macro-0.24.1/LICENSE +0 -21
- package/LICENSES/dependencies/defmt-1.1.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/defmt-1.1.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/defmt-macros-1.1.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/defmt-macros-1.1.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/defmt-parser-1.0.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/defmt-parser-1.0.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/deranged-0.5.8/LICENSE-Apache +0 -202
- package/LICENSES/dependencies/deranged-0.5.8/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/derive_more-2.1.1/LICENSE +0 -21
- package/LICENSES/dependencies/derive_more-impl-2.1.1/LICENSE +0 -21
- package/LICENSES/dependencies/dyn-clone-1.0.20/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/dyn-clone-1.0.20/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/either-1.18.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/either-1.18.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/equivalent-1.0.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/equivalent-1.0.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/errno-0.3.14/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/errno-0.3.14/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/event-listener-5.4.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/event-listener-5.4.2/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/event-listener-strategy-0.5.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/event-listener-strategy-0.5.4/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/fallible-iterator-0.3.0/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/fallible-iterator-0.3.0/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/fastrand-2.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/fastrand-2.5.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/find-msvc-tools-0.1.12/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/find-msvc-tools-0.1.12/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/fixedbitset-0.5.7/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/fixedbitset-0.5.7/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/foldhash-0.2.0/LICENSE +0 -19
- package/LICENSES/dependencies/futures-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-channel-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-channel-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-concurrency-7.7.1/LICENSE-APACHE +0 -190
- package/LICENSES/dependencies/futures-concurrency-7.7.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/futures-core-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-core-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-executor-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-executor-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-io-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-io-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/futures-lite-2.6.1/LICENSE-THIRD-PARTY +0 -45
- package/LICENSES/dependencies/futures-macro-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-macro-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-sink-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-sink-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-task-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-task-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/futures-util-0.3.34/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/futures-util-0.3.34/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/getrandom-0.4.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/getrandom-0.4.3/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/gimli-0.32.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/gimli-0.32.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hashbrown-0.12.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hashbrown-0.12.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hashbrown-0.16.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hashbrown-0.16.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hashbrown-0.17.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hashbrown-0.17.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/heck-0.5.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/heck-0.5.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/hermit-abi-0.5.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/hermit-abi-0.5.3/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/hex-0.4.3/LICENSE-APACHE +0 -202
- package/LICENSES/dependencies/hex-0.4.3/LICENSE-MIT +0 -20
- package/LICENSES/dependencies/iana-time-zone-0.1.65/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/iana-time-zone-0.1.65/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/iana-time-zone-haiku-0.1.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/iana-time-zone-haiku-0.1.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/id-arena-2.3.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/id-arena-2.3.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/ident_case-1.0.1/LICENSE +0 -19
- package/LICENSES/dependencies/indexmap-1.9.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/indexmap-1.9.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/indexmap-2.14.2/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/indexmap-2.14.2/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/itoa-1.0.18/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/itoa-1.0.18/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/jiff-0.2.35/COPYING +0 -3
- package/LICENSES/dependencies/jiff-0.2.35/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-0.2.35/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-core-0.1.0/COPYING +0 -3
- package/LICENSES/dependencies/jiff-core-0.1.0/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-core-0.1.0/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-static-0.2.35/COPYING +0 -3
- package/LICENSES/dependencies/jiff-static-0.2.35/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-static-0.2.35/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/COPYING +0 -3
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-tzdb-0.1.8/UNLICENSE +0 -24
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/COPYING +0 -3
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/jiff-tzdb-platform-0.1.3/UNLICENSE +0 -24
- package/LICENSES/dependencies/js-sys-0.3.105/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/js-sys-0.3.105/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/leb128-0.2.7/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/leb128-0.2.7/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/leb128fmt-0.1.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/leb128fmt-0.1.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/libc-0.2.189/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/libc-0.2.189/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/COPYRIGHT +0 -29
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/linux-raw-sys-0.12.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/log-0.4.34/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/log-0.4.34/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/memchr-2.8.3/COPYING +0 -3
- package/LICENSES/dependencies/memchr-2.8.3/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/memchr-2.8.3/UNLICENSE +0 -24
- package/LICENSES/dependencies/mio-1.2.3/LICENSE +0 -19
- package/LICENSES/dependencies/num-conv-0.2.2/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/num-conv-0.2.2/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/num-traits-0.2.19/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/num-traits-0.2.19/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/once_cell-1.21.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/once_cell-1.21.4/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/parking-2.2.1/LICENSE-THIRD-PARTY +0 -9
- package/LICENSES/dependencies/pin-project-1.1.13/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/pin-project-1.1.13/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/pin-project-internal-1.1.13/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/pin-project-internal-1.1.13/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/pin-project-lite-0.2.17/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/pin-project-lite-0.2.17/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/piper-0.2.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/piper-0.2.5/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/polling-3.11.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/polling-3.11.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/portable-atomic-1.15.0/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/portable-atomic-1.15.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/portable-atomic-util-0.2.8/LICENSE-APACHE +0 -177
- package/LICENSES/dependencies/portable-atomic-util-0.2.8/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/powerfmt-0.2.0/LICENSE-Apache +0 -202
- package/LICENSES/dependencies/powerfmt-0.2.0/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/proc-macro2-1.0.107/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/proc-macro2-1.0.107/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/quote-1.0.47/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/quote-1.0.47/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/r-efi-6.0.0/AUTHORS +0 -75
- package/LICENSES/dependencies/rayon-1.12.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rayon-1.12.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/rayon-core-1.13.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rayon-core-1.13.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/ref-cast-1.0.27/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/ref-cast-1.0.27/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/ref-cast-impl-1.0.27/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/ref-cast-impl-1.0.27/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/rustc-demangle-0.1.28/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rustc-demangle-0.1.28/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/rustc-hash-2.1.3/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/rustc-hash-2.1.3/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/rustc_version-0.4.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rustc_version-0.4.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/rustix-1.1.4/COPYRIGHT +0 -29
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/rustix-1.1.4/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/rustversion-1.0.23/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/rustversion-1.0.23/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/schemars-0.9.0/LICENSE +0 -21
- package/LICENSES/dependencies/schemars-1.2.2/LICENSE +0 -21
- package/LICENSES/dependencies/schemars_derive-1.2.2/LICENSE +0 -21
- package/LICENSES/dependencies/semver-1.0.28/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/semver-1.0.28/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde-1.0.229/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde-1.0.229/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_core-1.0.229/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_core-1.0.229/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_derive-1.0.229/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_derive-1.0.229/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_derive_internals-0.30.0/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_derive_internals-0.30.0/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_json-1.0.151/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/serde_json-1.0.151/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/serde_with-3.23.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/serde_with-3.23.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/serde_with_macros-3.23.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/serde_with_macros-3.23.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/shell-words-1.1.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/shell-words-1.1.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/shlex-2.0.1/LICENSE-APACHE +0 -13
- package/LICENSES/dependencies/shlex-2.0.1/LICENSE-MIT +0 -21
- package/LICENSES/dependencies/signal-hook-registry-1.4.8/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/signal-hook-registry-1.4.8/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/slab-0.4.12/LICENSE +0 -25
- package/LICENSES/dependencies/smallvec-1.16.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/smallvec-1.16.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/socket2-0.6.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/socket2-0.6.5/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/stable_deref_trait-1.2.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/stable_deref_trait-1.2.1/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/strsim-0.11.1/LICENSE +0 -23
- package/LICENSES/dependencies/strum-0.28.0/LICENSE +0 -21
- package/LICENSES/dependencies/strum_macros-0.28.0/LICENSE +0 -21
- package/LICENSES/dependencies/syn-2.0.119/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/syn-2.0.119/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/syn-3.0.5/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/syn-3.0.5/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/thiserror-2.0.20/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/thiserror-2.0.20/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/thiserror-impl-2.0.20/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/thiserror-impl-2.0.20/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/time-0.3.55/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/time-0.3.55/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/time-core-0.1.9/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/time-core-0.1.9/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/time-macros-0.2.32/LICENSE-Apache +0 -177
- package/LICENSES/dependencies/time-macros-0.2.32/LICENSE-MIT +0 -19
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-APACHE.md +0 -202
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-MIT.md +0 -5
- package/LICENSES/dependencies/tinyvec-1.13.2/LICENSE-ZLIB.md +0 -11
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-APACHE.md +0 -202
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-MIT.md +0 -21
- package/LICENSES/dependencies/tinyvec_macros-0.1.1/LICENSE-ZLIB.md +0 -20
- package/LICENSES/dependencies/tokio-1.53.1/LICENSE +0 -21
- package/LICENSES/dependencies/tokio-macros-2.7.2/LICENSE +0 -22
- package/LICENSES/dependencies/tracing-0.1.44/LICENSE +0 -25
- package/LICENSES/dependencies/tracing-attributes-0.1.31/LICENSE +0 -25
- package/LICENSES/dependencies/tracing-core-0.1.36/LICENSE +0 -25
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-APACHE +0 -176
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/unicode-ident-1.0.24/LICENSE-UNICODE +0 -39
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/COPYRIGHT +0 -7
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/unicode-segmentation-1.13.3/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/unicode-xid-0.2.6/COPYRIGHT +0 -7
- package/LICENSES/dependencies/unicode-xid-0.2.6/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/unicode-xid-0.2.6/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/uuid-1.26.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/uuid-1.26.1/LICENSE-MIT +0 -26
- package/LICENSES/dependencies/walrus-0.26.5/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/walrus-0.26.5/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/walrus-macro-0.26.0/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/walrus-macro-0.26.0/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/wasm-bindgen-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-cli-support-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-cli-support-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-macro-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-macro-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-macro-support-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-macro-support-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-bindgen-shared-0.2.128/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-bindgen-shared-0.2.128/LICENSE-MIT +0 -25
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/wasm-encoder-0.245.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-APACHE +0 -201
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/LICENSES/dependencies/wasmparser-0.245.1/LICENSE-MIT +0 -23
- package/LICENSES/dependencies/windows-core-0.62.2/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-core-0.62.2/license-mit +0 -21
- package/LICENSES/dependencies/windows-implement-0.60.2/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-implement-0.60.2/license-mit +0 -21
- package/LICENSES/dependencies/windows-interface-0.59.3/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-interface-0.59.3/license-mit +0 -21
- package/LICENSES/dependencies/windows-link-0.2.1/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-link-0.2.1/license-mit +0 -21
- package/LICENSES/dependencies/windows-result-0.4.1/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-result-0.4.1/license-mit +0 -21
- package/LICENSES/dependencies/windows-strings-0.5.1/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-strings-0.5.1/license-mit +0 -21
- package/LICENSES/dependencies/windows-sys-0.61.2/license-apache-2.0 +0 -201
- package/LICENSES/dependencies/windows-sys-0.61.2/license-mit +0 -21
- package/LICENSES/dependencies/zmij-1.0.23/LICENSE-MIT +0 -23
- package/THIRD-PARTY.md +0 -45
- package/source/.cargo/config.toml +0 -5
- package/source/.ci/upstream-notices/PROVENANCE.json +0 -198
- package/source/.ci/upstream-notices/agent-client-protocol-2.1.0/LICENSE +0 -191
- package/source/.ci/upstream-notices/agent-client-protocol-derive-2.1.0/LICENSE +0 -191
- package/source/.ci/upstream-notices/agent-client-protocol-schema-1.7.0/LICENSE +0 -190
- package/source/.ci/upstream-notices/defmt-parser-1.0.0/LICENSE-APACHE +0 -201
- package/source/.ci/upstream-notices/defmt-parser-1.0.0/LICENSE-MIT +0 -25
- package/source/.ci/upstream-notices/r-efi-6.0.0/AUTHORS +0 -75
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-APACHE +0 -201
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/source/.ci/upstream-notices/wasm-encoder-0.245.1/LICENSE-MIT +0 -23
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-APACHE +0 -201
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
- package/source/.ci/upstream-notices/wasmparser-0.245.1/LICENSE-MIT +0 -23
- package/source/.ci/wasm-bundle/Cargo.toml +0 -10
- package/source/.ci/wasm-bundle/src/main.rs +0 -17
- package/source/CHANGELOG.md +0 -11
- package/source/Cargo.lock +0 -1622
- package/source/Cargo.toml +0 -48
- package/source/LICENSE +0 -307
- package/source/LICENSE.md +0 -25
- package/source/LICENSES/GPL-3.0-only.txt +0 -232
- package/source/LICENSES/LGPL-3.0-only.txt +0 -304
- package/source/README.md +0 -185
- package/source/THIRD-PARTY.md +0 -45
- package/source/dependencies.tar.gz +0 -0
- package/source/examples/native.rs +0 -45
- package/source/src/conversation.rs +0 -557
- package/source/src/lib.rs +0 -27
- package/source/src/native/client.rs +0 -417
- package/source/src/native/fixture.py +0 -104
- package/source/src/native/mod.rs +0 -249
- package/source/src/native/session.rs +0 -541
- package/source/src/native/tests.rs +0 -427
- package/source/src/web.rs +0 -35
package/README.md
CHANGED
|
@@ -1,185 +1,216 @@
|
|
|
1
|
-
# ccht
|
|
1
|
+
# @corbet-labs/ccht
|
|
2
2
|
|
|
3
|
-
Reusable conversations for
|
|
4
|
-
**ccht** keeps the conversation model in Rust and compiles
|
|
5
|
-
that same model to Wasm. Native hosts connect to installed agents using the
|
|
6
|
-
[official ACP Rust SDK](https://github.com/agentclientprotocol/rust-sdk).
|
|
3
|
+
Reusable conversations for your applications, powered by the shared Rust/Wasm model.
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
The root entry (`createConversation`) owns the conversation state machine. The
|
|
6
|
+
`./auth` entry adds typed auth/challenge models mirroring `ccht::auth`, the
|
|
7
|
+
`./dock` entry adds framework-free dock state, and
|
|
8
|
+
`./components/AccountConnection.svelte` adds the first shared Svelte 5 account
|
|
9
|
+
connector alongside the generic `./components/Dock.svelte` edge rail. All
|
|
10
|
+
entries are product-neutral: no product names, prompts, or
|
|
11
|
+
pricing appear in this package.
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import { createConversation } from '@corbet-labs/ccht';
|
|
15
|
+
import { isAuthenticated, validateChallenge } from '@corbet-labs/ccht/auth';
|
|
16
|
+
import { createDockManager, validateDockId } from '@corbet-labs/ccht/dock';
|
|
17
|
+
import AccountConnection from '@corbet-labs/ccht/components/AccountConnection.svelte';
|
|
18
|
+
import Dock from '@corbet-labs/ccht/components/Dock.svelte';
|
|
12
19
|
```
|
|
13
20
|
|
|
14
|
-
The
|
|
15
|
-
|
|
16
|
-
instructions, context, tools, user authorization, storage and HTTP/WebSocket/SSE
|
|
17
|
-
transport. No Corbet-specific prompts or database are required.
|
|
21
|
+
The Svelte component ships as source and needs `svelte` `^5` (a peer
|
|
22
|
+
dependency). It has no other dependencies and imports no CSS framework.
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
ccht does not implement an agent loop, read provider credentials, install agents,
|
|
21
|
-
call paid model HTTP APIs or select an API-key fallback.
|
|
24
|
+
## What is shared vs what the app owns
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
Shared (this package):
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```
|
|
28
|
+
- Conversation state and ordered event replay (Wasm `ConversationModel`).
|
|
29
|
+
- Auth/challenge types and validators (`AuthState`, `Challenge`,
|
|
30
|
+
`CredentialsProvider`).
|
|
31
|
+
- Presentational account connector markup with stable styling hooks.
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
Owned by the embedding application:
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
- Transport: delivering `WireEvent`s (HTTP/WebSocket/SSE), serving the Wasm
|
|
36
|
+
bytes, and polling login operations until they complete.
|
|
37
|
+
- Effects: spawning agents, starting or cancelling logins, signing out. These
|
|
38
|
+
never run in browser library code; the component drives them through
|
|
39
|
+
app-supplied async callbacks and the app backend does the work.
|
|
40
|
+
- Storage: where credentials persist (OS keychain natively, origin-scoped
|
|
41
|
+
browser storage on the web). The library defines the interface only.
|
|
42
|
+
- Product copy: account labels, help text, links, and error wording beyond the
|
|
43
|
+
component's generic strings.
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
let mut conversation = Conversation::new("workspace/creator");
|
|
41
|
-
conversation.apply(WireEvent::new(
|
|
42
|
-
"workspace/creator", "turn-1", 1,
|
|
43
|
-
Event::Update {
|
|
44
|
-
update: acp::SessionUpdate::AgentMessageChunk(
|
|
45
|
-
acp::ContentChunk::new("Hello".into()),
|
|
46
|
-
),
|
|
47
|
-
},
|
|
48
|
-
)).unwrap();
|
|
49
|
-
assert_eq!(conversation.turns()[0].text, "Hello");
|
|
50
|
-
```
|
|
45
|
+
Rule: browser code in this package never spawns agents, performs network I/O,
|
|
46
|
+
or holds ambient authority. Service keys are explicit strings passed by the
|
|
47
|
+
app, and secrets are opaque bytes that are never logged.
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
supplied installed ACP executable. It requires native agent authentication already
|
|
54
|
-
configured by the operator. Use `codex-acp`, `claude-agent-acp`, or `opencode acp`
|
|
55
|
-
as separate, reviewed runtime installations. Generic ACP executables also work.
|
|
56
|
-
No agent/runtime is bundled in the crate or browser package.
|
|
57
|
-
|
|
58
|
-
`NativeClient::connect` initializes the protocol. Create a session with its working
|
|
59
|
-
directory, explicit model (if desired) and application MCP servers. Take the event
|
|
60
|
-
receiver before prompting and consume it concurrently with the prompt future.
|
|
61
|
-
A session accepts one active prompt; another returns `Busy`. Different sessions
|
|
62
|
-
have separate streams and permission identities. History load/resume and model
|
|
63
|
-
selection require the agent's advertised capabilities; unsupported requests fail.
|
|
64
|
-
|
|
65
|
-
Permissions default to denial. Applications that opt into asking must render the
|
|
66
|
-
request, check their authority and respond with one of the advertised choices.
|
|
67
|
-
A permission callback is not a sandbox: agent-owned tools may have separate runtime
|
|
68
|
-
policy. Configure filesystem/network confinement in the host for your use case.
|
|
69
|
-
ccht advertises no client filesystem or terminal capabilities.
|
|
70
|
-
|
|
71
|
-
Cancellation asks the upstream agent to stop. If it does not stop within the
|
|
72
|
-
configured shutdown timeout, ccht closes the SDK connection, affecting **all**
|
|
73
|
-
sessions on that connection. Dropping an active prompt also closes its connection.
|
|
74
|
-
Use one connection per independent workload when cancellation must be isolated.
|
|
75
|
-
Bounded event channels fail explicitly on an unresponsive consumer.
|
|
76
|
-
|
|
77
|
-
`AgentCommand::with_working_directory` sets the actual agent startup directory
|
|
78
|
-
using installed Linux/macOS `env` launchers. Windows currently reports this helper
|
|
79
|
-
as unsupported because the SDK launch configuration lacks a startup-directory
|
|
80
|
-
field. Session cwd alone does not constrain files read during agent startup.
|
|
81
|
-
Linux is covered by process-level tests; macOS support is source-reviewed.
|
|
82
|
-
|
|
83
|
-
ACP enables `serde_json`'s `preserve_order` feature through Cargo feature
|
|
84
|
-
unification. Applications that hash or sign JSON must explicitly canonicalize
|
|
85
|
-
object keys; depending on a `Value` map's incidental iteration order is unsafe.
|
|
86
|
-
|
|
87
|
-
## Browser
|
|
88
|
-
|
|
89
|
-
```sh
|
|
90
|
-
npm install @corbet-labs/ccht
|
|
91
|
-
```
|
|
49
|
+
## Auth entry (`@corbet-labs/ccht/auth`)
|
|
92
50
|
|
|
93
|
-
|
|
94
|
-
import { createConversation } from '@corbet-labs/ccht';
|
|
95
|
-
// Vite example: emit the Wasm as a separately replaceable asset.
|
|
96
|
-
import wasmUrl from '@corbet-labs/ccht/ccht_bg.wasm?url';
|
|
97
|
-
|
|
98
|
-
const conversation = await createConversation('workspace/creator', { wasm: wasmUrl });
|
|
99
|
-
// After your authenticated application transport delivers a ccht WireEvent:
|
|
100
|
-
const snapshot = conversation.applyEvent(event);
|
|
101
|
-
render(snapshot.turns);
|
|
102
|
-
// When the view is destroyed:
|
|
103
|
-
conversation.free();
|
|
104
|
-
```
|
|
51
|
+
Plain types and functions, no DOM access.
|
|
105
52
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
`WireEvent` version 1 contains `conversation_id`, `request_id`, a per-request
|
|
115
|
-
`sequence` starting at 1, and `event`. Retain the original structured ACP updates:
|
|
116
|
-
text, non-text content, tool calls, thought chunks, plans, permissions and errors
|
|
117
|
-
are distinct. The model returns a serializable snapshot for your renderer.
|
|
118
|
-
|
|
119
|
-
Assign identities and sequences on a trusted application host. Never let a browser
|
|
120
|
-
select another user's conversation without server-side authorization. Sequence
|
|
121
|
-
numbers are **not** SSE cursors or database row IDs. The app stores its own event
|
|
122
|
-
log and replays each request in order. Already-applied sequences are ignored;
|
|
123
|
-
gaps, a different conversation, malformed events and new events after completion
|
|
124
|
-
fail without mutating state. Delivery identity must not be reused for another turn.
|
|
125
|
-
|
|
126
|
-
A model holds at most 256 turns, 8 MiB per turn and 1 MiB per event. Applications
|
|
127
|
-
should page long histories into separate models and limit streamed inputs before
|
|
128
|
-
parsing them. Durable transcript storage and reconnection are application concerns;
|
|
129
|
-
a serialized snapshot is a render result, not a native-agent session checkpoint.
|
|
130
|
-
|
|
131
|
-
Namer is the first integration: Creator/Critic have independent conversation
|
|
132
|
-
scopes, durable application events, authenticated SSE and cancellation. Its queue
|
|
133
|
-
uses a fresh native session per turn with bounded role history supplied by Namer.
|
|
134
|
-
CareerVector's TUI reuses the native session API while keeping CV tools, prompts
|
|
135
|
-
and revision checks in its own code. Explicit local inference can emit the same
|
|
136
|
-
`WireEvent` contract through an application-owned backend.
|
|
137
|
-
|
|
138
|
-
## Building the Wasm package
|
|
139
|
-
|
|
140
|
-
Use Rust with `wasm32-unknown-unknown` installed. The checked-in generator uses the
|
|
141
|
-
same exact `wasm-bindgen` version as the Rust crate; no global Wasm CLI is required.
|
|
142
|
-
|
|
143
|
-
```sh
|
|
144
|
-
cargo build --locked --release --no-default-features --features web --target wasm32-unknown-unknown
|
|
145
|
-
cargo run --locked --release -p ccht-wasm-bundle -- target/wasm32-unknown-unknown/release/ccht.wasm web/wasm
|
|
146
|
-
```
|
|
53
|
+
`AuthState` mirrors the Rust `snake_case` JSON byte-for-byte:
|
|
54
|
+
|
|
55
|
+
| Rust | JSON | TypeScript |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `Unknown` | `"unknown"` | `'unknown'` |
|
|
58
|
+
| `Unauthenticated` | `"unauthenticated"` | `'unauthenticated'` |
|
|
59
|
+
| `Authenticated { account }` | `{"authenticated": {"account": "…"}}` | `{ authenticated: { account?: string \| null } }` |
|
|
147
60
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
`
|
|
151
|
-
|
|
61
|
+
Helpers: `isAuthenticated(state)` mirrors `AuthState::authenticated`,
|
|
62
|
+
`authAccount(state)` returns the display-only label (or null), and
|
|
63
|
+
`parseAuthState(value)` / `isAuthState(value)` validate decoded JSON. The
|
|
64
|
+
label is provenance for the UI, never an authentication proof.
|
|
152
65
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
66
|
+
`Challenge` is `{ verification_url, user_code }`. The backend issues it, pins
|
|
67
|
+
any provider-specific endpoint, and polls for completion; the browser only
|
|
68
|
+
renders a validated challenge. `validateChallenge(value)` accepts an `https:`
|
|
69
|
+
URL with a host (no embedded credentials) and a non-empty code of up to 64
|
|
70
|
+
ASCII alphanumeric or `-` characters. It never throws, so callers can gate
|
|
71
|
+
rendering on it. The component validates internally and renders waiting text
|
|
72
|
+
for a missing or malformed challenge instead of an unvalidated link.
|
|
73
|
+
|
|
74
|
+
`CredentialsProvider` mirrors the Rust trait with JS method names:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
interface CredentialsProvider {
|
|
78
|
+
readCredentials(service: string): Promise<Credential | null>;
|
|
79
|
+
writeCredentials(service: string, credential: Credential): Promise<void>;
|
|
80
|
+
deleteCredentials(service: string): Promise<void>;
|
|
81
|
+
}
|
|
158
82
|
```
|
|
159
83
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
84
|
+
`Credential` is `{ account: string; secret: Uint8Array }`. Encode at the app
|
|
85
|
+
boundary (`TextEncoder`/base64) when the store needs text. Service keys are
|
|
86
|
+
app-defined (for example `assistant-login:<provider>`); deleting a missing
|
|
87
|
+
entry succeeds, and a rejected promise signals store failure. There is no
|
|
88
|
+
environment-variable override on the web: the store alone decides, matching
|
|
89
|
+
the documented `ApiKeyState` behavior on Wasm.
|
|
90
|
+
|
|
91
|
+
## Component (`AccountConnection.svelte`)
|
|
92
|
+
|
|
93
|
+
Svelte 5 runes. Props:
|
|
94
|
+
|
|
95
|
+
| Prop | Type | Meaning |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| `account` | `{ id: string; label: string; kind: 'chatgpt' \| 'opencode_go' \| string }` | Product-neutral identity. Known kinds select the ceremony; unknown kinds fall back to a generic sign-in button. |
|
|
98
|
+
| `state` | `AuthState` | Observed login state (defaults to `'unknown'`). |
|
|
99
|
+
| `busy` | `boolean` | An app-owned operation is in flight; actions disable, cancel shows. |
|
|
100
|
+
| `challenge` | `Challenge \| null` (optional) | Device-code challenge supplied by the app after `onStart` starts polling. |
|
|
101
|
+
| `onStart` | `() => void \| Promise<void>` | Begin the login ceremony (for example start a device flow). |
|
|
102
|
+
| `onCancel` | `() => void \| Promise<void>` | Abort the in-flight operation; also backs Disconnect when `onDisconnect` is omitted. |
|
|
103
|
+
| `onKeySubmit` | `(key: string) => void \| Promise<void>` | Persist a trimmed account key (minimum 8 characters). |
|
|
104
|
+
| `onDisconnect` | optional | Sign out when authenticated. Falls back to `onCancel`, which can branch on app state. |
|
|
105
|
+
|
|
106
|
+
Rendering:
|
|
107
|
+
|
|
108
|
+
- Unauthenticated `chatgpt`: sign-in button, then waiting text while `busy`,
|
|
109
|
+
then the device-code view (code, copy button, sign-in link) once a valid
|
|
110
|
+
`challenge` arrives. The copy button opens the link during the click (so
|
|
111
|
+
popup blockers do not trigger) and falls back to a manual-copy message when
|
|
112
|
+
the clipboard API is unavailable.
|
|
113
|
+
- Unauthenticated `opencode_go`: password key form that clears on submit.
|
|
114
|
+
- Authenticated: connection status with the account label (when known) and a
|
|
115
|
+
Disconnect button.
|
|
116
|
+
- `unknown` state: neutral checking text with no ceremony buttons.
|
|
117
|
+
|
|
118
|
+
Callbacks are fire-and-forget from the component's view: the app must handle
|
|
119
|
+
its own failures and surface them through its own operation state, which it
|
|
120
|
+
renders outside the component. Callback rejections are therefore ignored here
|
|
121
|
+
by design.
|
|
122
|
+
|
|
123
|
+
Accessibility: semantic `section`/`form`/`label`/`button` elements, an
|
|
124
|
+
`aria-label` naming the account connection, `role="status"` for status lines,
|
|
125
|
+
an `aria-live="polite"` region announcing challenge arrival, and
|
|
126
|
+
`role="alert"` for the clipboard fallback. The key input is labelled,
|
|
127
|
+
password-masked, and non-persistent.
|
|
128
|
+
|
|
129
|
+
## Dock entry (`@corbet-labs/ccht/dock`) and component (`Dock.svelte`)
|
|
130
|
+
|
|
131
|
+
Framework-free dock state plus a generic Svelte 5 edge rail. `DockKind`
|
|
132
|
+
(`'chat' | 'config' | 'custom'`) classifies a dock and `Placement`
|
|
133
|
+
(`'left' | 'right' | 'bottom' | 'inline'`) places it. The state module is
|
|
134
|
+
plain TypeScript with no DOM access.
|
|
135
|
+
|
|
136
|
+
`validateDockId(id)` returns an error message or null (never throws). Rules:
|
|
137
|
+
a non-empty string of at most 64 ASCII `[a-z0-9-_]` characters.
|
|
138
|
+
|
|
139
|
+
`createDockManager()` returns an independent manager:
|
|
140
|
+
|
|
141
|
+
| Method | Meaning |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| `register(id, kind, placement)` | Register a closed dock. Throws the validation message for a malformed id, `DuplicateDock: <id>` for a repeat. |
|
|
144
|
+
| `open(id)` / `close(id)` | Mark a dock open or closed. Unknown ids throw `UnknownDock: <id>`. |
|
|
145
|
+
| `openWithFocus(id, token)` | Open a dock and stage an opaque focus token (non-empty string) for the app to consume. |
|
|
146
|
+
| `toggle(id)` | Flip a dock's open state and return the new state. |
|
|
147
|
+
| `isOpen(id)` | Whether a dock is open. |
|
|
148
|
+
| `placement(id)` / `setPlacement(id, placement)` | Read or move a dock's placement. Invalid placements throw `invalid dock placement`. |
|
|
149
|
+
| `openDocks()` | Ids of open docks, in registration order. |
|
|
150
|
+
| `takeFocusToken()` | Take the staged focus token once, clearing it; null when none is staged. |
|
|
151
|
+
| `closeAll()` | Mark every dock closed. |
|
|
152
|
+
| `serialize()` | Persist `[{id, kind, placement, open}]` as JSON, in registration order. The focus token is never persisted. |
|
|
153
|
+
| `restore(json)` | Replace all state from `serialize` output. Every entry is validated first, so a malformed snapshot (thrown as `invalid dock snapshot: …`) leaves current state untouched, and any staged focus token is cleared. |
|
|
154
|
+
|
|
155
|
+
`Dock.svelte` renders one named dock as an edge rail for the `left` and
|
|
156
|
+
`right` placements. Svelte 5 runes. Props:
|
|
157
|
+
|
|
158
|
+
| Prop | Type | Meaning |
|
|
159
|
+
| --- | --- | --- |
|
|
160
|
+
| `side` | `'left' \| 'right'` | Which window edge the rail pins to. |
|
|
161
|
+
| `title` | `string` | Panel heading and dialog label. |
|
|
162
|
+
| `open` | `boolean` | App-owned visibility state. |
|
|
163
|
+
| `onClose` | `() => void` | Close intent (tab is hidden while open; Esc key also closes). |
|
|
164
|
+
| `onOpen` | `() => void` | Open intent from the edge tab button. |
|
|
165
|
+
| `tabLabel` | `string` | Short tab caption. |
|
|
166
|
+
| `tabSummary` | `string` (optional, defaults to `''`) | Detail shown in the tab button and panel head. |
|
|
167
|
+
| `closeLabel` | optional `string` | Close button label (defaults to `Close {title}`). |
|
|
168
|
+
| `panelId` | `string` | Panel element id, referenced by the tab's `aria-controls`. |
|
|
169
|
+
| `children` | `Snippet` | Panel body content. |
|
|
170
|
+
|
|
171
|
+
Rendering:
|
|
172
|
+
|
|
173
|
+
- Closed: a fixed edge tab button (`aria-expanded="false"`,
|
|
174
|
+
`aria-controls={panelId}`, labelled `Open {title}: {tabSummary}` or
|
|
175
|
+
`Open {title}`). The panel stays mounted but hidden and inert.
|
|
176
|
+
- Open: a `role="dialog"` panel with a head (`h2` title, summary paragraph,
|
|
177
|
+
Close button) and a body rendering `children`.
|
|
178
|
+
- Opening moves focus to the first visible, enabled control in the panel
|
|
179
|
+
(or the panel itself); closing returns focus to the tab or the previously
|
|
180
|
+
focused element. Esc closes.
|
|
181
|
+
- The `bottom` and `inline` placements are state-only: they persist and
|
|
182
|
+
restore through the manager but have no rail chrome here. Custom hosts
|
|
183
|
+
(for example a ratatui overlay or an inline sheet) render them.
|
|
184
|
+
|
|
185
|
+
Stable classes: `ccht-dock-tab`, `ccht-dock-tab-text`, `ccht-dock-panel`,
|
|
186
|
+
`ccht-dock-head`, `ccht-dock-title`, `ccht-dock-close`, `ccht-dock-body`.
|
|
187
|
+
The tab and panel carry `data-side` (`left` / `right`) and the panel carries
|
|
188
|
+
`data-open` (`true` / `false`).
|
|
189
|
+
|
|
190
|
+
CSS variables (with fallbacks when unset): `--ccht-fg`, `--ccht-muted`,
|
|
191
|
+
`--ccht-accent`, `--ccht-border`, `--ccht-panel-bg`, `--ccht-tab-bg`,
|
|
192
|
+
`--ccht-tab-bg-hover`, `--ccht-fg-bright`.
|
|
193
|
+
|
|
194
|
+
Rule: the app owns dock effects. The manager never persists, the component
|
|
195
|
+
never fetches, spawns, or stores; visibility, persistence, and focus targets
|
|
196
|
+
beyond the panel run through app callbacks and app-held state.
|
|
197
|
+
|
|
198
|
+
## Styling hooks
|
|
199
|
+
|
|
200
|
+
Unstyled-but-hooked markup: layout comes from the app, colors resolve through
|
|
201
|
+
CSS custom properties with plain fallbacks. Stable classes:
|
|
202
|
+
|
|
203
|
+
`ccht-account`, `ccht-status`, `ccht-hint`, `ccht-error`, `ccht-challenge`,
|
|
204
|
+
`ccht-code`, `ccht-button`, `ccht-cancel`, `ccht-disconnect`, `ccht-link`,
|
|
205
|
+
`ccht-keyform`, `ccht-label`, `ccht-input`.
|
|
206
|
+
|
|
207
|
+
CSS variables (with fallbacks when unset): `--ccht-fg`, `--ccht-muted`,
|
|
208
|
+
`--ccht-error`, `--ccht-accent`, `--ccht-code-bg`. Example:
|
|
209
|
+
|
|
210
|
+
```css
|
|
211
|
+
:root {
|
|
212
|
+
--ccht-muted: #a5b5cb;
|
|
213
|
+
--ccht-error: #fda4af;
|
|
214
|
+
--ccht-accent: #7bb8ff;
|
|
215
|
+
}
|
|
216
|
+
```
|
package/index.d.ts
CHANGED
|
@@ -35,13 +35,28 @@ export interface TurnState {
|
|
|
35
35
|
stop_reason: string | null;
|
|
36
36
|
error: { code: string; message: string } | null;
|
|
37
37
|
}
|
|
38
|
-
export interface
|
|
38
|
+
export interface ConfigChoice { value: string; name: string; description?: string }
|
|
39
|
+
export interface ConfigGroup { group: string; name: string; options: ConfigChoice[] }
|
|
40
|
+
export type SessionConfigOption = {
|
|
41
|
+
id: string; name: string; description?: string; category?: string;
|
|
42
|
+
} & ({ type: 'select'; currentValue: string; options: ConfigChoice[] | ConfigGroup[] }
|
|
43
|
+
| { type: 'boolean'; currentValue: boolean });
|
|
44
|
+
export interface SessionConfiguration {
|
|
45
|
+
options: SessionConfigOption[];
|
|
46
|
+
modes: null | { currentModeId: string; availableModes: Array<{id: string; name: string; description?: string}> };
|
|
47
|
+
}
|
|
48
|
+
export interface ConversationSnapshot { conversation_id: string; turns: TurnState[]; configuration: SessionConfiguration }
|
|
39
49
|
export interface Conversation {
|
|
40
50
|
applyEvent(event: WireEvent | string): ConversationSnapshot;
|
|
41
51
|
snapshot(): ConversationSnapshot;
|
|
42
52
|
free(): void;
|
|
43
53
|
}
|
|
44
|
-
/** Transport/authentication and persistence belong to the embedding application.
|
|
54
|
+
/** Transport/authentication and persistence belong to the embedding application.
|
|
55
|
+
*
|
|
56
|
+
* Only the first call's `wasm` option initializes the shared module; later
|
|
57
|
+
* calls reuse it. `applyEvent` returns the fresh snapshot and throws on
|
|
58
|
+
* invalid, out-of-scope, gapped, terminal, or freed input. `free` is idempotent.
|
|
59
|
+
*/
|
|
45
60
|
export function createConversation(conversationId: string, options?: {
|
|
46
61
|
wasm?: URL | string | Request | Response | BufferSource | WebAssembly.Module;
|
|
47
62
|
}): Promise<Conversation>;
|
package/index.js
CHANGED
|
@@ -3,7 +3,14 @@ import initialize, { ConversationModel } from './wasm/ccht.js';
|
|
|
3
3
|
|
|
4
4
|
let initialization;
|
|
5
5
|
|
|
6
|
-
/** Initialize the shared Rust/Wasm model. Supply an explicit Wasm URL when bundling.
|
|
6
|
+
/** Initialize the shared Rust/Wasm model. Supply an explicit Wasm URL when bundling.
|
|
7
|
+
*
|
|
8
|
+
* Only the first call's `wasm` option initializes the shared module; later
|
|
9
|
+
* calls reuse it. The returned `applyEvent` applies one ordered event and
|
|
10
|
+
* returns the fresh snapshot (the underlying Rust boolean for "changed" is
|
|
11
|
+
* not exposed); it throws on invalid JSON, scope, gap, terminal, or freed
|
|
12
|
+
* state. `snapshot` returns the parsed render state and `free` is idempotent.
|
|
13
|
+
*/
|
|
7
14
|
export async function createConversation(conversationId, options = {}) {
|
|
8
15
|
if (!initialization) {
|
|
9
16
|
initialization = initialize(options.wasm === undefined ? undefined : { module_or_path: options.wasm })
|
package/package.json
CHANGED
|
@@ -1,36 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corbet-labs/ccht",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Reusable conversations for your applications, powered by the shared Rust/Wasm model",
|
|
5
|
-
"license": "LGPL-3.0-only",
|
|
5
|
+
"license": "LGPL-3.0-only WITH LGPL-3.0-linking-exception",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./index.js",
|
|
8
8
|
"types": "./index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
".": { "types": "./index.d.ts", "import": "./index.js" },
|
|
11
|
+
"./auth": { "types": "./src/auth.ts", "import": "./src/auth.ts" },
|
|
12
|
+
"./dock": { "types": "./src/dock.ts", "import": "./src/dock.ts" },
|
|
13
|
+
"./components/AccountConnection.svelte": "./src/components/AccountConnection.svelte",
|
|
14
|
+
"./components/Dock.svelte": "./src/components/Dock.svelte",
|
|
14
15
|
"./ccht_bg.wasm": "./wasm/ccht_bg.wasm"
|
|
15
16
|
},
|
|
16
|
-
"files": [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"LICENSE",
|
|
22
|
-
"LICENSE.md",
|
|
23
|
-
"LICENSES/",
|
|
24
|
-
"README.md",
|
|
25
|
-
"THIRD-PARTY.md"
|
|
26
|
-
],
|
|
27
|
-
"repository": {
|
|
28
|
-
"type": "git",
|
|
29
|
-
"url": "git+https://github.com/corbet-labs/ccht.git"
|
|
30
|
-
},
|
|
31
|
-
"publishConfig": {
|
|
32
|
-
"access": "public"
|
|
33
|
-
},
|
|
34
|
-
"sideEffects": false,
|
|
35
|
-
"gitHead": "340b9c2d41c77c2c1448666ddad8cd28307517bd"
|
|
17
|
+
"files": ["index.js", "index.d.ts", "src/", "wasm/", "source/", "LICENSE", "LICENSE.md", "LICENSES/", "README.md", "THIRD-PARTY.md"],
|
|
18
|
+
"repository": { "type": "git", "url": "git+https://github.com/corbet-labs/ccht.git" },
|
|
19
|
+
"publishConfig": { "access": "public" },
|
|
20
|
+
"peerDependencies": { "svelte": "^5" },
|
|
21
|
+
"sideEffects": false
|
|
36
22
|
}
|
package/src/auth.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/** Typed mirrors of the Rust auth surface (`ccht::auth`) for web consumers.
|
|
2
|
+
*
|
|
3
|
+
* The conversation model stays in Rust/Wasm; these types only describe *who*
|
|
4
|
+
* may act. Transport, login ceremonies, credential storage, polling and
|
|
5
|
+
* product copy belong to the embedding application. Nothing here touches the
|
|
6
|
+
* DOM, performs network I/O, or spawns processes: effects run in the
|
|
7
|
+
* application backend and reach the browser through app-supplied async
|
|
8
|
+
* callbacks and explicit service keys.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Login state of one provider, mirroring `ccht::auth::AuthState`.
|
|
12
|
+
*
|
|
13
|
+
* The shape round-trips the Rust `snake_case` JSON byte-for-byte, so a state
|
|
14
|
+
* serialized by Rust deserializes here and vice versa:
|
|
15
|
+
* - `Unknown` becomes the string `"unknown"`.
|
|
16
|
+
* - `Unauthenticated` becomes the string `"unauthenticated"`.
|
|
17
|
+
* - `Authenticated { account }` becomes `{"authenticated": {"account": ...}}`,
|
|
18
|
+
* where `account` is a display-only label (string), `null`, or absent.
|
|
19
|
+
* The label is provenance for the UI and never an authentication proof.
|
|
20
|
+
*/
|
|
21
|
+
export type AuthState = 'unknown' | 'unauthenticated' | { authenticated: { account?: string | null } };
|
|
22
|
+
|
|
23
|
+
/** Whether routine work may proceed without prompting for login first. Mirrors `AuthState::authenticated`. */
|
|
24
|
+
export function isAuthenticated(state: AuthState): boolean {
|
|
25
|
+
return typeof state === 'object' && state !== null && 'authenticated' in state;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Display-only account label (username, email, or subscription name), or null when absent. Never a secret. */
|
|
29
|
+
export function authAccount(state: AuthState): string | null {
|
|
30
|
+
if (typeof state === 'object' && state !== null && 'authenticated' in state) {
|
|
31
|
+
return state.authenticated.account ?? null;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Whether a decoded JSON value has the exact Rust `AuthState` shape. Unknown fields inside the inner object are ignored, matching serde's default. */
|
|
37
|
+
export function isAuthState(value: unknown): value is AuthState {
|
|
38
|
+
try {
|
|
39
|
+
parseAuthState(value);
|
|
40
|
+
return true;
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Validate a decoded JSON value as the Rust `AuthState` shape. Throws a `TypeError` when the shape differs. */
|
|
47
|
+
export function parseAuthState(value: unknown): AuthState {
|
|
48
|
+
if (value === 'unknown' || value === 'unauthenticated') {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
52
|
+
const keys = Object.keys(value);
|
|
53
|
+
if (keys.length === 1 && keys[0] === 'authenticated') {
|
|
54
|
+
const inner = (value as { authenticated: unknown }).authenticated;
|
|
55
|
+
if (typeof inner === 'object' && inner !== null && !Array.isArray(inner)) {
|
|
56
|
+
const account = (inner as { account?: unknown }).account;
|
|
57
|
+
if (account === undefined) {
|
|
58
|
+
return { authenticated: {} };
|
|
59
|
+
}
|
|
60
|
+
if (account === null || typeof account === 'string') {
|
|
61
|
+
return { authenticated: { account } };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw new TypeError('invalid AuthState');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Device-code challenge as exchanged during a provider login ceremony.
|
|
70
|
+
*
|
|
71
|
+
* Field names stay `snake_case` to match the wire format applications pass
|
|
72
|
+
* between their backend and the browser. The backend remains authoritative:
|
|
73
|
+
* it issues the challenge, pins any provider-specific endpoint, and polls
|
|
74
|
+
* for completion. The browser only displays a validated challenge and never
|
|
75
|
+
* invents one.
|
|
76
|
+
*/
|
|
77
|
+
export interface Challenge {
|
|
78
|
+
verification_url: string;
|
|
79
|
+
user_code: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const CHALLENGE_CODE_PATTERN = /^[A-Za-z0-9-]+$/;
|
|
83
|
+
const CHALLENGE_CODE_MAX_LENGTH = 64;
|
|
84
|
+
|
|
85
|
+
/** Whether a value is a renderable device-code challenge.
|
|
86
|
+
*
|
|
87
|
+
* Accepts any `https:` URL with a host (applications may narrow this
|
|
88
|
+
* further, for example by pinning the provider's device endpoint) and a
|
|
89
|
+
* non-empty code of up to 64 ASCII alphanumeric or `-` characters. URLs with
|
|
90
|
+
* embedded credentials are rejected. Never throws; validate before rendering
|
|
91
|
+
* a challenge as a link or code.
|
|
92
|
+
*/
|
|
93
|
+
export function validateChallenge(value: unknown): value is Challenge {
|
|
94
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const { verification_url, user_code } = value as Record<string, unknown>;
|
|
98
|
+
if (typeof verification_url !== 'string' || typeof user_code !== 'string') {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (user_code.length < 1 || user_code.length > CHALLENGE_CODE_MAX_LENGTH) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (!CHALLENGE_CODE_PATTERN.test(user_code)) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
let url: URL;
|
|
108
|
+
try {
|
|
109
|
+
url = new URL(verification_url);
|
|
110
|
+
} catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (url.protocol !== 'https:' || url.hostname === '') {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
if (url.username !== '' || url.password !== '') {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Opaque credential, mirroring `ccht::auth::Credential`.
|
|
123
|
+
*
|
|
124
|
+
* Stores treat both fields as opaque. `account` is display-only; `secret`
|
|
125
|
+
* holds the raw secret bytes. Encode at the application boundary (for
|
|
126
|
+
* example with `TextEncoder` or base64) when the backing store needs text,
|
|
127
|
+
* and never write secrets to logs, errors, or fixtures.
|
|
128
|
+
*/
|
|
129
|
+
export interface Credential {
|
|
130
|
+
account: string;
|
|
131
|
+
secret: Uint8Array;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Application-supplied credential persistence, mirroring `ccht::auth::CredentialsProvider`.
|
|
135
|
+
*
|
|
136
|
+
* One method triple per service key. Service keys are application-defined
|
|
137
|
+
* opaque strings (never ambient authority); native applications back this
|
|
138
|
+
* with the OS keychain and web applications with origin-scoped browser
|
|
139
|
+
* storage. Removing a missing entry succeeds. Implementations reject the
|
|
140
|
+
* promise when the backing store fails.
|
|
141
|
+
*/
|
|
142
|
+
export interface CredentialsProvider {
|
|
143
|
+
/** Read stored credentials, if any, for a service key. */
|
|
144
|
+
readCredentials(service: string): Promise<Credential | null>;
|
|
145
|
+
/** Persist credentials for a service key, replacing any previous entry. */
|
|
146
|
+
writeCredentials(service: string, credential: Credential): Promise<void>;
|
|
147
|
+
/** Remove stored credentials for a service key. Missing entries are not an error. */
|
|
148
|
+
deleteCredentials(service: string): Promise<void>;
|
|
149
|
+
}
|