@innspel/core 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Niclas Amundsen
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.
package/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # @innspel/core
2
+
3
+ Kjernen i Innspels SDK. Ren TypeScript: ingen nettleser-API-er, ingen
4
+ runtime-avhengigheter (K19), ingen stabil identifikator på enheten (K20).
5
+ Lagring og identitet injiseres av verten.
6
+
7
+ Bygger du en React Native-app, installer [`@innspel/react-native`](../react-native)
8
+ i stedet — den gir deg widgeten og en lagringsadapter, og bruker denne pakken under.
9
+
10
+ ```bash
11
+ npm install @innspel/core
12
+ ```
13
+
14
+ ## Quickstart
15
+
16
+ ```ts
17
+ import { init } from '@innspel/core';
18
+
19
+ const innspel = init({
20
+ baseUrl: 'https://api.innspel.example', // din plattform-URL
21
+ tenantKey: 'ik_pub_xxxxxxxx', // offentlig SDK-nøkkel fra panelet
22
+ identityProvider: hentFeedbackToken, // eller null = anonym modus
23
+ storage, // se «Lagring» under
24
+ context: { platform: 'ios', appVersion: '1.4.2' },
25
+ });
26
+
27
+ await innspel.capture({ type: 'feil', text: 'Dørlista er tom etter kl. 22.' });
28
+ ```
29
+
30
+ Det er hele veien til første innsending. Alt annet under er valgfritt.
31
+
32
+ ## De fire opsjonene du må gi
33
+
34
+ | Opsjon | Hva |
35
+ |---|---|
36
+ | `baseUrl` | Plattformens API-rot. Ingen standard — SDK-et skal aldri gjette hvor dataene dine havner. |
37
+ | `tenantKey` | Den offentlige SDK-nøkkelen. Skrivende, bundet til bundle-ID eller origin, kan aldri lese andres data (K3). Den hører hjemme i appens konfig, ikke i en hemmelighet. |
38
+ | `identityProvider` | Funksjon som gir et ferskt feedback-token, eller `null` for anonym modus. Se under. |
39
+ | `storage` | Tre metoder. Offline-køen bor her. |
40
+
41
+ `context.platform` er påkrevd; `appVersion`, `build`, `os`, `screen` og `locale` er
42
+ valgfrie. Feltlista er en **lukket hviteliste** (K5) — et ukjent felt avvises av
43
+ plattformen med `unknown_field`, og SDK-et sender aldri enhets-ID eller IP.
44
+
45
+ ### Identitet
46
+
47
+ Plattformen eier aldri sluttbrukerne dine. Du utsteder et kortlevd token, den
48
+ verifiserer det og lærer aldri hvem det peker på:
49
+
50
+ ```ts
51
+ const hentFeedbackToken = async () => {
52
+ const res = await fetch('https://din-app.example/api/innspel-token', {
53
+ headers: { Authorization: `Bearer ${dinEgenSesjon}` },
54
+ });
55
+ return (await res.json()).token; // ES256-JWT, aud=innspel, exp ≤ 15 min
56
+ };
57
+ ```
58
+
59
+ Token-endepunktet er det eneste du må bygge selv.
60
+ [Integrasjonsguiden](../../../docs/sdk/README.md) viser det med kjørbar kode.
61
+
62
+ `identityProvider: null` er **anonym modus**: innsendinger sendes uten avsender,
63
+ teller aldri i distinkt Reach og kan ikke følges opp. Det er et eksplisitt valg —
64
+ en glemt opsjon gir en feilmelding, aldri stille anonymitet.
65
+
66
+ Kaster funksjonen din, eller returnerer den `null`, faller SDK-et tilbake til
67
+ anonym modus for det kallet og logger `[innspel]` til konsollen. Innsenderen skal
68
+ kunne melde fra selv om innloggingen din er nede.
69
+
70
+ ### Lagring
71
+
72
+ ```ts
73
+ interface InnspelStorage {
74
+ get(key: string): Promise<string | null>;
75
+ set(key: string, value: string): Promise<void>;
76
+ remove(key: string): Promise<void>;
77
+ }
78
+ ```
79
+
80
+ Bruk hva du vil — MMKV, AsyncStorage, SQLite, et objekt i minnet.
81
+ `@innspel/react-native` gir deg en ferdig.
82
+
83
+ ## API
84
+
85
+ ```ts
86
+ innspel.capture({ type, text, context?, correlation?, relatedKnownIssueId?, clientRef? })
87
+ innspel.knownIssues.for({ screen?, version?, platform? }) // kortene som vises FØR feltet
88
+ innspel.knownIssues.confirm(id) // «Ja, jeg også» — Reach +1, ingen ny sak
89
+ innspel.subjects.submissions() // «Mine innspill», inkl. det som venter på nett
90
+ innspel.subjects.status(submissionId) // status for én egen innsending
91
+ innspel.programs.list() // invitasjoner, deltakelser, oppfølginger
92
+ innspel.queue.pending() // det som ligger i offline-køen
93
+ innspel.queue.flush() // sendes ellers automatisk
94
+ innspel.scanText(text) // mønstervarsel, se under
95
+ innspel.openFeedback() // krever @innspel/react-native
96
+ ```
97
+
98
+ Alt er dokumentert med TSDoc i editoren din. Typene er generert fra API-kontrakten,
99
+ så feltdokumentasjonen er den samme som plattformen håndhever.
100
+
101
+ ### Offline-køen
102
+
103
+ Faller nettet, køes innsendingen lokalt — **kun teksten**, aldri et skjermbilde.
104
+ Taket er 30; innsending nummer 31 avvises med en synlig melding i stedet for å
105
+ kaste den eldste (DD-41). Køen tømmes når widgeten åpnes eller nettet kommer
106
+ tilbake, **aldri ved oppstart**, og hver flush henter et ferskt token — det gamle
107
+ er utløpt for lengst.
108
+
109
+ Vis køen for brukeren. `queue.pending()` gir deg radene, og «Venter på nett —
110
+ sendes automatisk» er teksten widgeten bruker.
111
+
112
+ ### Mønstervarsel
113
+
114
+ ```ts
115
+ innspel.scanText('Kontoen min er kari@example.com');
116
+ // [{ kind: 'email', match: 'kari@example.com', start: 15, end: 32 }]
117
+ ```
118
+
119
+ Finner e-post, telefonnummer, kortnummer (Luhn-validert), IP-adresser og
120
+ token-lignende strenger. **Den fjerner aldri noe** (DD-46) — du viser funnet,
121
+ brukeren velger «Fjern» eller «Behold». Innsenderen skal alltid se hva som sendes.
122
+
123
+ ### Telemetri
124
+
125
+ ```ts
126
+ init({ …, telemetry: { emit: (e) => minAnalytics.track(e.name, e) } });
127
+ ```
128
+
129
+ Standard er `noop`. Hendelsene bærer aldri tekst, skjermbilde eller pseudonym.
130
+ Utelater du opsjonen, sendes ingenting noe sted.
131
+
132
+ ## Feil
133
+
134
+ Alt fra plattformen kommer som `InnspelApiError` med en `code` du kan forgrene på —
135
+ aldri på meldingsteksten:
136
+
137
+ ```ts
138
+ try {
139
+ await innspel.capture({ type: 'feil', text });
140
+ } catch (e) {
141
+ if (e instanceof InnspelApiError && e.code === 'text_too_short') { … }
142
+ }
143
+ ```
144
+
145
+ `feedback_token_expired` håndteres internt: SDK-et ber `identityProvider` om et
146
+ nytt token og prøver på nytt, én gang. Den ser du aldri.
147
+
148
+ ## Versjoner
149
+
150
+ Semver fra `0.1.0`. **Før `1.0.0` kan en minor bryte** — pin en eksakt versjon om
151
+ du trenger ro. Endringer i API-kontrakten er alltid minst minor, fordi de er en
152
+ SDK-endring hos deg.
153
+
154
+ ## Grenser SDK-et holder
155
+
156
+ - Ingen tredjeparts-SDK: ingen analytics, ingen crash-rapportering, ingen annonser (K19)
157
+ - Ingen install-ID, ingen device-ID, ingen fingeravtrykk (K20). `clientRef` er en ny
158
+ UUID per innsending og identifiserer aldri enheten
159
+ - Ingen nettleser-API-er: `localStorage`, `document`, `window` og `navigator` finnes
160
+ ikke i denne pakken
161
+ - Under 10 kB gzip
162
+
163
+ ## Lisens
164
+
165
+ MIT. Klientpakkene er permissivt lisensiert fordi koden kjører hos deg og må
166
+ kunne leses og granskes der. Plattformen bak — API, panel og drift — er det ikke.