@qafka/react-native 2.0.0
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/CHANGELOG.md +12 -0
- package/CONTRIBUTING.md +92 -0
- package/LICENSE +22 -0
- package/README.md +109 -0
- package/SECURITY.md +67 -0
- package/android/build.gradle +35 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/qafka/attestation/QafkaAttestationModule.kt +92 -0
- package/android/src/main/java/com/qafka/attestation/QafkaAttestationPackage.kt +22 -0
- package/android/src/main/java/com/qafka/audio/QafkaAudioModule.kt +290 -0
- package/android/src/main/java/com/qafka/clipboard/QafkaClipboardModule.kt +28 -0
- package/android/src/main/java/com/qafka/storage/QafkaStorageModule.kt +80 -0
- package/app.plugin.js +1 -0
- package/dist/QafkaSDK.d.ts +174 -0
- package/dist/QafkaSDK.js +461 -0
- package/dist/cards/bindings/resolveFieldName.d.ts +25 -0
- package/dist/cards/bindings/resolveFieldName.js +82 -0
- package/dist/cards/cta/CardContext.d.ts +16 -0
- package/dist/cards/cta/CardContext.js +58 -0
- package/dist/cards/cta/dispatcher.d.ts +7 -0
- package/dist/cards/cta/dispatcher.js +90 -0
- package/dist/cards/cta/types.d.ts +66 -0
- package/dist/cards/cta/types.js +2 -0
- package/dist/cards/index.d.ts +20 -0
- package/dist/cards/index.js +34 -0
- package/dist/cards/primitives/QButton.d.ts +10 -0
- package/dist/cards/primitives/QButton.js +115 -0
- package/dist/cards/primitives/QDivider.d.ts +7 -0
- package/dist/cards/primitives/QDivider.js +17 -0
- package/dist/cards/primitives/QIcon.d.ts +13 -0
- package/dist/cards/primitives/QIcon.js +26 -0
- package/dist/cards/primitives/QImage.d.ts +9 -0
- package/dist/cards/primitives/QImage.js +22 -0
- package/dist/cards/primitives/QText.d.ts +9 -0
- package/dist/cards/primitives/QText.js +30 -0
- package/dist/cards/primitives/QView.d.ts +8 -0
- package/dist/cards/primitives/QView.js +19 -0
- package/dist/cards/renderer/CardRenderer.d.ts +19 -0
- package/dist/cards/renderer/CardRenderer.js +64 -0
- package/dist/cards/renderer/renderNode.d.ts +13 -0
- package/dist/cards/renderer/renderNode.js +42 -0
- package/dist/cards/types.d.ts +110 -0
- package/dist/cards/types.js +6 -0
- package/dist/components/ActionResultBadge.d.ts +12 -0
- package/dist/components/ActionResultBadge.js +58 -0
- package/dist/components/ChatPage.d.ts +44 -0
- package/dist/components/ChatPage.js +84 -0
- package/dist/components/DataChip.d.ts +8 -0
- package/dist/components/DataChip.js +80 -0
- package/dist/components/DataChipList.d.ts +13 -0
- package/dist/components/DataChipList.js +21 -0
- package/dist/components/FloatingButton.d.ts +11 -0
- package/dist/components/FloatingButton.js +162 -0
- package/dist/components/InputArea.d.ts +57 -0
- package/dist/components/InputArea.js +142 -0
- package/dist/components/MarkdownText.d.ts +15 -0
- package/dist/components/MarkdownText.js +283 -0
- package/dist/components/MessageBubble.d.ts +134 -0
- package/dist/components/MessageBubble.js +384 -0
- package/dist/components/NavigationSuggestion.d.ts +11 -0
- package/dist/components/NavigationSuggestion.js +109 -0
- package/dist/components/Qafka.d.ts +39 -0
- package/dist/components/Qafka.handlers.d.ts +21 -0
- package/dist/components/Qafka.handlers.js +54 -0
- package/dist/components/Qafka.js +493 -0
- package/dist/components/Qafka.styles.d.ts +19 -0
- package/dist/components/Qafka.styles.js +101 -0
- package/dist/components/Qafka.types.d.ts +744 -0
- package/dist/components/Qafka.types.js +2 -0
- package/dist/components/Qafka.utils.d.ts +7 -0
- package/dist/components/Qafka.utils.js +34 -0
- package/dist/components/QafkaProvider.d.ts +12 -0
- package/dist/components/QafkaProvider.js +87 -0
- package/dist/components/QuickReplies.d.ts +14 -0
- package/dist/components/QuickReplies.js +48 -0
- package/dist/components/StepProgressIndicator.d.ts +12 -0
- package/dist/components/StepProgressIndicator.js +48 -0
- package/dist/components/SuggestionButton.d.ts +42 -0
- package/dist/components/SuggestionButton.js +67 -0
- package/dist/components/ToolStatusPill.d.ts +20 -0
- package/dist/components/ToolStatusPill.js +43 -0
- package/dist/components/TypingIndicator.d.ts +28 -0
- package/dist/components/TypingIndicator.js +109 -0
- package/dist/components/VoicePage.d.ts +48 -0
- package/dist/components/VoicePage.js +683 -0
- package/dist/components/defaults/DefaultCard.d.ts +14 -0
- package/dist/components/defaults/DefaultCard.js +156 -0
- package/dist/components/defaults/DefaultDetail.d.ts +14 -0
- package/dist/components/defaults/DefaultDetail.js +138 -0
- package/dist/components/defaults/DefaultList.d.ts +12 -0
- package/dist/components/defaults/DefaultList.js +98 -0
- package/dist/components/defaults/DefaultTable.d.ts +14 -0
- package/dist/components/defaults/DefaultTable.js +204 -0
- package/dist/components/defaults/index.d.ts +14 -0
- package/dist/components/defaults/index.js +25 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.js +36 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +13 -0
- package/dist/hooks/useChatMessages.d.ts +72 -0
- package/dist/hooks/useChatMessages.js +505 -0
- package/dist/hooks/useContextManager.d.ts +12 -0
- package/dist/hooks/useContextManager.js +46 -0
- package/dist/hooks/useProjectTheme.d.ts +19 -0
- package/dist/hooks/useProjectTheme.js +163 -0
- package/dist/hooks/useSDK.d.ts +31 -0
- package/dist/hooks/useSDK.js +103 -0
- package/dist/hooks/useVoiceChat.d.ts +110 -0
- package/dist/hooks/useVoiceChat.js +436 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +59 -0
- package/dist/native/QafkaAttestation.d.ts +23 -0
- package/dist/native/QafkaAttestation.js +70 -0
- package/dist/native/QafkaAudio.d.ts +14 -0
- package/dist/native/QafkaAudio.js +31 -0
- package/dist/native/QafkaClipboard.d.ts +11 -0
- package/dist/native/QafkaClipboard.js +14 -0
- package/dist/native/QafkaStorage.d.ts +15 -0
- package/dist/native/QafkaStorage.js +12 -0
- package/dist/resolve-project-config.d.ts +35 -0
- package/dist/resolve-project-config.js +41 -0
- package/dist/runtime-config-loader.d.ts +37 -0
- package/dist/runtime-config-loader.js +53 -0
- package/dist/services/AttestationManager.d.ts +38 -0
- package/dist/services/AttestationManager.js +296 -0
- package/dist/services/BackendService.d.ts +156 -0
- package/dist/services/BackendService.js +755 -0
- package/dist/services/ConversationManager.d.ts +43 -0
- package/dist/services/ConversationManager.js +96 -0
- package/dist/services/NavigationHandler.d.ts +29 -0
- package/dist/services/NavigationHandler.js +70 -0
- package/dist/services/RealtimeService.d.ts +83 -0
- package/dist/services/RealtimeService.js +203 -0
- package/dist/services/storage.d.ts +11 -0
- package/dist/services/storage.js +15 -0
- package/dist/services/storageCore.d.ts +17 -0
- package/dist/services/storageCore.js +46 -0
- package/dist/themes/dark.d.ts +5 -0
- package/dist/themes/dark.js +129 -0
- package/dist/themes/index.d.ts +12 -0
- package/dist/themes/index.js +33 -0
- package/dist/themes/light.d.ts +5 -0
- package/dist/themes/light.js +129 -0
- package/dist/themes/types.d.ts +155 -0
- package/dist/themes/types.js +5 -0
- package/dist/types/chat.d.ts +126 -0
- package/dist/types/chat.js +5 -0
- package/dist/types/components.d.ts +56 -0
- package/dist/types/components.js +16 -0
- package/dist/types/external-navigation.d.ts +19 -0
- package/dist/types/external-navigation.js +8 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.js +25 -0
- package/dist/types/navigation.d.ts +86 -0
- package/dist/types/navigation.js +5 -0
- package/dist/types/sdk.d.ts +36 -0
- package/dist/types/sdk.js +5 -0
- package/dist/utils/deepMerge.d.ts +46 -0
- package/dist/utils/deepMerge.js +70 -0
- package/dist/utils/fontUtils.d.ts +8 -0
- package/dist/utils/fontUtils.js +16 -0
- package/dist/validate-end-user.d.ts +18 -0
- package/dist/validate-end-user.js +74 -0
- package/expo-plugin/withQafkaAttestation.js +57 -0
- package/ios/QafkaAttestation.m +25 -0
- package/ios/QafkaAttestation.swift +128 -0
- package/ios/QafkaAudio.m +23 -0
- package/ios/QafkaAudio.swift +519 -0
- package/ios/QafkaClipboard.m +10 -0
- package/ios/QafkaClipboard.swift +21 -0
- package/ios/QafkaReactImports.h +2 -0
- package/ios/QafkaStorage.m +26 -0
- package/ios/QafkaStorage.swift +118 -0
- package/package.json +82 -0
- package/qafka.config.d.ts +9 -0
- package/qafka.config.js +9 -0
- package/react-native-qafka.podspec +28 -0
- package/react-native.config.js +14 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@qafka/react-native` are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [2.0.0] — 2026-05-17
|
|
11
|
+
|
|
12
|
+
Initial public release. See [README.md](./README.md) for the full feature list and installation instructions.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in Qafka.
|
|
4
|
+
|
|
5
|
+
## About this repository
|
|
6
|
+
|
|
7
|
+
This is the official React Native SDK for the [Qafka platform](https://qafka.com). It's MIT-licensed and the source is public — audit it, debug it, pin a specific commit, fork it if you need.
|
|
8
|
+
|
|
9
|
+
Day-to-day development happens on our internal roadmap, and we accept a curated set of external contributions — see below.
|
|
10
|
+
|
|
11
|
+
## Reporting bugs
|
|
12
|
+
|
|
13
|
+
Please use [GitHub Issues](https://github.com/qafka-ai/react-native-qafka/issues) and the bug report template. Helpful reports include:
|
|
14
|
+
|
|
15
|
+
- SDK version, React Native version, platform (iOS / Android / Expo)
|
|
16
|
+
- A minimal reproduction
|
|
17
|
+
- Logs (with API keys redacted)
|
|
18
|
+
|
|
19
|
+
For **security issues**, see [SECURITY.md](./SECURITY.md) — please do not file them as public issues.
|
|
20
|
+
|
|
21
|
+
## Requesting features
|
|
22
|
+
|
|
23
|
+
Open a [GitHub Issue](https://github.com/qafka-ai/react-native-qafka/issues) describing the use case. We'll respond with whether it fits the roadmap and the likely timing.
|
|
24
|
+
|
|
25
|
+
**Please do not send feature PRs without a tracking issue and our explicit go-ahead.** We may decline merges that don't fit our direction, even if the code is good — please don't take it personally.
|
|
26
|
+
|
|
27
|
+
## Pull requests we accept
|
|
28
|
+
|
|
29
|
+
- 🐛 **Bug fixes** with a reproducing test
|
|
30
|
+
- 📝 **Documentation fixes** — typos, broken links, clarifications
|
|
31
|
+
- 🔧 **Build / tooling fixes** — broken CI, packaging issues
|
|
32
|
+
- ♿ **Accessibility fixes** to the rendered components
|
|
33
|
+
|
|
34
|
+
## Pull requests we usually decline
|
|
35
|
+
|
|
36
|
+
- New features without a prior issue
|
|
37
|
+
- Pure refactors / restyles
|
|
38
|
+
- Dependency updates (we manage these on a release cadence)
|
|
39
|
+
- Code style changes that aren't enforced by our linter
|
|
40
|
+
|
|
41
|
+
## Dev setup
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://github.com/qafka-ai/react-native-qafka.git
|
|
45
|
+
cd react-native-qafka
|
|
46
|
+
pnpm install
|
|
47
|
+
pnpm build
|
|
48
|
+
pnpm test
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
To test changes locally in another app, we use [yalc](https://github.com/wclr/yalc):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
yalc publish --push --force --private
|
|
55
|
+
# in the consuming app:
|
|
56
|
+
yalc add @qafka/react-native
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Pull request checklist
|
|
60
|
+
|
|
61
|
+
Before opening a PR:
|
|
62
|
+
|
|
63
|
+
- [ ] Linked to a tracking issue
|
|
64
|
+
- [ ] Branch is up to date with `main`
|
|
65
|
+
- [ ] Tests added / updated for the change
|
|
66
|
+
- [ ] `pnpm typecheck` passes
|
|
67
|
+
- [ ] `pnpm test` passes
|
|
68
|
+
- [ ] `CHANGELOG.md` updated under `## [Unreleased]`
|
|
69
|
+
- [ ] Commits are signed off (DCO — see below)
|
|
70
|
+
|
|
71
|
+
## Developer Certificate of Origin (DCO)
|
|
72
|
+
|
|
73
|
+
We require commits to be signed off with the [Developer Certificate of Origin](https://developercertificate.org/). This is a lightweight assertion that you have the right to submit your contribution.
|
|
74
|
+
|
|
75
|
+
Sign off by adding `-s` to your commit:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
git commit -s -m "fix: handle empty tool result"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
This appends a `Signed-off-by: Your Name <your.email@example.com>` line to your commit message.
|
|
82
|
+
|
|
83
|
+
By signing off and contributing, you agree your contributions are licensed under the [MIT License](./LICENSE).
|
|
84
|
+
|
|
85
|
+
## Code of Conduct
|
|
86
|
+
|
|
87
|
+
Be respectful in issues, PRs, and discussions. We follow the [Contributor Covenant](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
|
88
|
+
|
|
89
|
+
## Questions
|
|
90
|
+
|
|
91
|
+
For product questions, billing, or sales: [qafka.com/contact](https://qafka.com).
|
|
92
|
+
For SDK technical questions: open a [Discussion](https://github.com/qafka-ai/react-native-qafka/discussions) or Issue.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Qafka
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# @qafka/react-native
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@qafka/react-native)
|
|
4
|
+
[](https://www.npmjs.com/package/@qafka/react-native)
|
|
5
|
+
[](https://www.npmjs.com/package/@qafka/react-native)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://github.com/qafka-ai/react-native-qafka/actions/workflows/ci.yml)
|
|
8
|
+
|
|
9
|
+
In-app AI assistant for React Native and Expo. Drop the `<Qafka />` component into your app and your users get a chat + voice interface that understands your screens, runs your tools, and guides them through flows you define in the [Qafka dashboard](https://app.qafka.com).
|
|
10
|
+
|
|
11
|
+
## Quickstart (recommended)
|
|
12
|
+
|
|
13
|
+
Install the CLI once, log in, then initialize Qafka in your app:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g qafka
|
|
17
|
+
|
|
18
|
+
cd your-app
|
|
19
|
+
qafka login
|
|
20
|
+
qafka init
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`qafka init` installs the SDK, registers the Expo config plugin (when applicable), pulls your API key from the dashboard, and scaffolds a chat screen wired to your project. Re-run it any time you add tools or screens in the dashboard — it's idempotent and safe.
|
|
24
|
+
|
|
25
|
+
## Manual installation
|
|
26
|
+
|
|
27
|
+
If you'd rather wire things up yourself:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @qafka/react-native
|
|
31
|
+
# or: pnpm add / yarn add
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Peer dependencies
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install react-native react-native-safe-area-context
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`@react-navigation/native` is optional — install it only if you want the SDK to navigate between screens for you.
|
|
41
|
+
|
|
42
|
+
### Expo
|
|
43
|
+
|
|
44
|
+
The package ships an Expo config plugin. Add it to your `app.json` / `app.config.js`:
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"expo": {
|
|
49
|
+
"plugins": ["@qafka/react-native"]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then run `npx expo prebuild` (or rebuild your dev client) so the native module is bundled.
|
|
55
|
+
|
|
56
|
+
### Bare React Native
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd ios && pod install
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Android autolinking handles the native module. If you plan to use **voice mode**, add the microphone permission to your app's `android/app/src/main/AndroidManifest.xml`:
|
|
63
|
+
|
|
64
|
+
```xml
|
|
65
|
+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Expo users get this automatically via the SDK's config plugin.
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
When your project is initialized with the [Qafka CLI](https://github.com/qafka-ai/qafka-cli) (`qafka init`), the SDK picks up your development key from the CLI-generated runtime config — no extra props needed:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { Qafka } from '@qafka/react-native';
|
|
76
|
+
|
|
77
|
+
export default function App() {
|
|
78
|
+
return <Qafka />;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The component renders a floating button that opens the chat UI. Configure tools, screens, and behavior from the dashboard — most updates need no code changes.
|
|
83
|
+
|
|
84
|
+
Pass `projectId` when your app has more than one registered project:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
<Qafka projectId="proj_abc123" />
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Documentation
|
|
91
|
+
|
|
92
|
+
Full guides, API reference, theming, voice mode, tools, and advanced configuration:
|
|
93
|
+
|
|
94
|
+
**→ [app.qafka.com/docs](https://app.qafka.com/docs)**
|
|
95
|
+
|
|
96
|
+
## Requirements
|
|
97
|
+
|
|
98
|
+
- React Native ≥ 0.72 (Expo SDK 49+ supported)
|
|
99
|
+
- React ≥ 18
|
|
100
|
+
- iOS 14+ / Android 6+ (API 23+)
|
|
101
|
+
- Node ≥ 20 (for build tooling)
|
|
102
|
+
|
|
103
|
+
## Contributing
|
|
104
|
+
|
|
105
|
+
This SDK is the public source for a commercial product — see [CONTRIBUTING.md](./CONTRIBUTING.md) for what we accept and how to file issues. For vulnerabilities, see [SECURITY.md](./SECURITY.md).
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT © Qafka
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
Qafka takes security seriously. This document describes how to report vulnerabilities in the **React Native SDK** (`@qafka/react-native`).
|
|
4
|
+
|
|
5
|
+
## Supported versions
|
|
6
|
+
|
|
7
|
+
Only the latest published minor version receives security updates. We recommend always running the latest version.
|
|
8
|
+
|
|
9
|
+
## Reporting a vulnerability
|
|
10
|
+
|
|
11
|
+
**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**
|
|
12
|
+
|
|
13
|
+
Instead, choose one of these private channels:
|
|
14
|
+
|
|
15
|
+
1. **Email:** [security@qafka.com](mailto:security@qafka.com)
|
|
16
|
+
2. **GitHub Security Advisories:** [Report a vulnerability privately](https://github.com/qafka-ai/react-native-qafka/security/advisories/new)
|
|
17
|
+
|
|
18
|
+
Please include:
|
|
19
|
+
|
|
20
|
+
- A clear description of the issue
|
|
21
|
+
- Steps to reproduce (a minimal repo or code snippet helps)
|
|
22
|
+
- Affected SDK version(s) and platforms (iOS / Android / Expo)
|
|
23
|
+
- Potential impact you've identified
|
|
24
|
+
- Any suggested fix, if you have one
|
|
25
|
+
|
|
26
|
+
If you'd like to encrypt your report, request our PGP key by emailing [security@qafka.com](mailto:security@qafka.com).
|
|
27
|
+
|
|
28
|
+
## What to expect
|
|
29
|
+
|
|
30
|
+
- **Acknowledgement:** within 2 business days of your report
|
|
31
|
+
- **Initial assessment:** within 5 business days
|
|
32
|
+
- **Status updates:** at least every 7 days until the issue is resolved
|
|
33
|
+
- **Coordinated disclosure:** we'll work with you on a public disclosure timeline once a fix is ready
|
|
34
|
+
- **Credit:** with your permission, we'll credit you in the release notes and the GitHub Security Advisory
|
|
35
|
+
|
|
36
|
+
## Scope
|
|
37
|
+
|
|
38
|
+
### In scope
|
|
39
|
+
|
|
40
|
+
This policy covers vulnerabilities in this SDK package that could affect customer applications:
|
|
41
|
+
|
|
42
|
+
- API key, token, or credential handling within the SDK
|
|
43
|
+
- Native module security (iOS Swift / Objective-C, Android Kotlin / Java)
|
|
44
|
+
- Data leakage between sessions, projects, or users on the same device
|
|
45
|
+
- Local storage / cache integrity
|
|
46
|
+
- Bundle / dependency supply-chain issues specific to this package
|
|
47
|
+
- Crash or denial-of-service triggerable from the SDK's public API
|
|
48
|
+
|
|
49
|
+
### Out of scope
|
|
50
|
+
|
|
51
|
+
- **Qafka backend (`api.qafka.com`)** — out of scope for this repository. If you find a backend issue, email [security@qafka.com](mailto:security@qafka.com) with `[backend]` in the subject.
|
|
52
|
+
- **Third-party dependencies** — please report to the upstream maintainer. If the issue is exploitable through our usage specifically, we'll accept it here.
|
|
53
|
+
- **Issues requiring a rooted / jailbroken device** or attacker-controlled physical access, unless the impact extends beyond the compromised device.
|
|
54
|
+
- **Social engineering** of Qafka customers or staff.
|
|
55
|
+
- **Outdated documentation** — please file a regular issue.
|
|
56
|
+
|
|
57
|
+
## Safe harbor
|
|
58
|
+
|
|
59
|
+
We will not pursue legal action against researchers who:
|
|
60
|
+
|
|
61
|
+
- Make a good-faith effort to follow this policy
|
|
62
|
+
- Avoid privacy violations, data destruction, and service disruption
|
|
63
|
+
- Give us reasonable time to fix the issue before public disclosure
|
|
64
|
+
|
|
65
|
+
## Questions
|
|
66
|
+
|
|
67
|
+
For anything not covered here, email [security@qafka.com](mailto:security@qafka.com).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apply plugin: 'com.android.library'
|
|
2
|
+
apply plugin: 'kotlin-android'
|
|
3
|
+
|
|
4
|
+
def safeExtGet(prop, fallback) {
|
|
5
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
android {
|
|
9
|
+
namespace "com.qafka.attestation"
|
|
10
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 34)
|
|
11
|
+
|
|
12
|
+
defaultConfig {
|
|
13
|
+
minSdkVersion safeExtGet('minSdkVersion', 24)
|
|
14
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 34)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
compileOptions {
|
|
18
|
+
sourceCompatibility JavaVersion.toVersion(safeExtGet('javaVersion', 17))
|
|
19
|
+
targetCompatibility JavaVersion.toVersion(safeExtGet('javaVersion', 17))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
kotlinOptions {
|
|
23
|
+
jvmTarget = safeExtGet('javaVersion', 17).toString()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
repositories {
|
|
28
|
+
google()
|
|
29
|
+
mavenCentral()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dependencies {
|
|
33
|
+
implementation 'com.facebook.react:react-android'
|
|
34
|
+
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
|
35
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
package com.qafka.attestation
|
|
2
|
+
|
|
3
|
+
import android.os.Build
|
|
4
|
+
import android.security.keystore.KeyGenParameterSpec
|
|
5
|
+
import android.security.keystore.KeyProperties
|
|
6
|
+
import android.util.Base64
|
|
7
|
+
import com.facebook.react.bridge.*
|
|
8
|
+
import java.security.KeyPairGenerator
|
|
9
|
+
import java.security.KeyStore
|
|
10
|
+
import java.security.cert.Certificate
|
|
11
|
+
|
|
12
|
+
class QafkaAttestationModule(reactContext: ReactApplicationContext) :
|
|
13
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
14
|
+
|
|
15
|
+
override fun getName(): String = "QafkaAttestation"
|
|
16
|
+
|
|
17
|
+
override fun getConstants(): MutableMap<String, Any> {
|
|
18
|
+
val context = reactApplicationContext
|
|
19
|
+
val bundleId = context.packageName ?: ""
|
|
20
|
+
val appVersion = try {
|
|
21
|
+
context.packageManager.getPackageInfo(context.packageName, 0).versionName ?: ""
|
|
22
|
+
} catch (e: Exception) {
|
|
23
|
+
""
|
|
24
|
+
}
|
|
25
|
+
val deviceModel = "${Build.MANUFACTURER} ${Build.MODEL}".trim()
|
|
26
|
+
return mutableMapOf(
|
|
27
|
+
"bundleId" to bundleId,
|
|
28
|
+
"appVersion" to appVersion,
|
|
29
|
+
"deviceModel" to deviceModel,
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@ReactMethod
|
|
34
|
+
fun isSupported(promise: Promise) {
|
|
35
|
+
// Key Attestation requires Android 8.0+ (API 26) for hardware-backed
|
|
36
|
+
promise.resolve(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@ReactMethod
|
|
40
|
+
fun generateKeyPair(alias: String, challengeBase64: String, promise: Promise) {
|
|
41
|
+
try {
|
|
42
|
+
val challenge = Base64.decode(challengeBase64, Base64.DEFAULT)
|
|
43
|
+
|
|
44
|
+
// Delete existing key if any
|
|
45
|
+
val keyStore = KeyStore.getInstance("AndroidKeyStore")
|
|
46
|
+
keyStore.load(null)
|
|
47
|
+
if (keyStore.containsAlias(alias)) {
|
|
48
|
+
keyStore.deleteEntry(alias)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
val keyPairGenerator = KeyPairGenerator.getInstance(
|
|
52
|
+
KeyProperties.KEY_ALGORITHM_EC,
|
|
53
|
+
"AndroidKeyStore"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
val builder = KeyGenParameterSpec.Builder(alias,
|
|
57
|
+
KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
|
|
58
|
+
)
|
|
59
|
+
.setDigests(KeyProperties.DIGEST_SHA256)
|
|
60
|
+
.setAttestationChallenge(challenge)
|
|
61
|
+
|
|
62
|
+
keyPairGenerator.initialize(builder.build())
|
|
63
|
+
keyPairGenerator.generateKeyPair()
|
|
64
|
+
|
|
65
|
+
promise.resolve(null)
|
|
66
|
+
} catch (e: Exception) {
|
|
67
|
+
promise.reject("KEY_GEN_FAILED", e.message, e)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@ReactMethod
|
|
72
|
+
fun getAttestationCertChain(alias: String, promise: Promise) {
|
|
73
|
+
try {
|
|
74
|
+
val keyStore = KeyStore.getInstance("AndroidKeyStore")
|
|
75
|
+
keyStore.load(null)
|
|
76
|
+
|
|
77
|
+
val chain: Array<Certificate> = keyStore.getCertificateChain(alias)
|
|
78
|
+
?: throw Exception("No certificate chain found for alias: $alias")
|
|
79
|
+
|
|
80
|
+
val result = Arguments.createArray()
|
|
81
|
+
for (cert in chain) {
|
|
82
|
+
val encoded = cert.encoded
|
|
83
|
+
val base64 = Base64.encodeToString(encoded, Base64.NO_WRAP)
|
|
84
|
+
result.pushString(base64)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
promise.resolve(result)
|
|
88
|
+
} catch (e: Exception) {
|
|
89
|
+
promise.reject("CERT_CHAIN_FAILED", e.message, e)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.qafka.attestation
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
import com.qafka.audio.QafkaAudioModule
|
|
8
|
+
import com.qafka.clipboard.QafkaClipboardModule
|
|
9
|
+
import com.qafka.storage.QafkaStorageModule
|
|
10
|
+
|
|
11
|
+
class QafkaAttestationPackage : ReactPackage {
|
|
12
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
|
|
13
|
+
listOf(
|
|
14
|
+
QafkaAttestationModule(reactContext),
|
|
15
|
+
QafkaAudioModule(reactContext),
|
|
16
|
+
QafkaClipboardModule(reactContext),
|
|
17
|
+
QafkaStorageModule(reactContext),
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
|
|
21
|
+
emptyList()
|
|
22
|
+
}
|