SIAX Technology (sax3l)

@siax/mobile-config (0.1.1)

Published 2026-08-10 12:03:21 +00:00 by admin

Installation

@siax:registry=https://git.cloud.siax.io/api/packages/sax3l/npm/
npm install @siax/mobile-config@0.1.1
"@siax/mobile-config": "0.1.1"

About this package

@siax/mobile-config

Fjärrconfig och feature flags för K6-appar. Bär minimumVersion / recommendedVersion (VER-04 / VER-05) och läser flaggor som Unleash redan utvärderat.

Status: implementerad och testad. 56/56 tester gröna (node --test), tsc --strict rent. Inte publicerad till Giteas npm-registry, och services/config är inte rest (M10) — transporten är därför injicerbar och paketet fungerar fullt ut mot en påhittad transport i test.

Kärnbussgränsen (MOB-02)

Detta paket är en yta, inte en tjänst.

Vad Vem äger det Vad vi gör
Feature flags Unleash (server10) läser ett färdigutvärderat dokument. Ingen strategimotor, ingen flaggdatabas, inget adminläge
Versionspolicy services/config i detta repo hämtar och cachar
Identitet / token ID0 tar emot ett token från en injicerad funktion
Hemligheter Infisical inga. baseUrl är en parameter, inget nyckelvärde finns i koden (SEC-01/MSEC-01)

Det paketet gör själv — för att ingen annan gör det åt en mobilklient — är semver-jämförelsen, grindbeslutet och offlinecachen.

Snabbstart

import {
  MobileConfigClient,
  createHttpConfigTransport,
} from '@siax/mobile-config';

const config = new MobileConfigClient({
  appVersion: '1.2.0',            // ur bundlen
  platform: 'ios',
  storage: minAsyncStorageAdapter, // valfri men KRÄVS för offline
  transport: createHttpConfigTransport({
    baseUrl: process.env.EXPO_PUBLIC_CONFIG_URL!, // env-NAMN, aldrig ett värde
    getAccessToken: () => auth.accessToken(),     // ID0, via @siax/mobile-auth
  }),
});

await config.hydrate();               // läs cachen INNAN första renderingen
const gate = await config.versionGate();

if (gate.blocking) {
  // VER-04: spärrskärm UTAN stängknapp. gate.storeUrl är garanterat ifylld här.
  visaSpärrskärm({ storeUrl: gate.storeUrl });
} else if (gate.status === 'update-recommended') {
  // VER-05: avfärdbar banner. Tydligt skild från spärrskärmen.
  visaUppmaning({ storeUrl: gate.storeUrl, avfärdbar: true });
}

if (config.isEnabled('ny-onboarding')) { /* … */ }

VER-04 / VER-05

evaluateVersionGate() är ren och synkron, så beslutet går att testa uttömmande och återge exakt i en incident.

Läge status blocking dismissible
Under minimumVersion update-required true false
Under recommendedVersion update-recommended false true
Aktuell / ingen policy ok false false

De två är ömsesidigt uteslutande — det är testat, inte bara påstått.

Semver på riktigt

semver.ts implementerar semver 2.0.0 §11 fullt ut, utan externt beroende:

  • 1.10.0 > 1.9.0 (inte strängjämförelse)
  • 1.0.0-beta < 1.0.0 (prerelease har lägre precedens)
  • hela kedjan alpha < alpha.1 < alpha.beta < beta < beta.2 < beta.11 < rc.1 < 1.0.0
  • numerisk identifierare < alfanumerisk; fler fält vinner vid lika prefix
  • byggmetadata (+sha.abc) ignoreras alltid

Tre fail-safe-regler som är medvetna, inte olyckor

  1. Oläsbar appversion ⇒ ingen spärr. Kan vi inte parsa vår egen version kan vi inte veta att den är för gammal. Att gissa låser ute hela installerade basen på ett byggfel.
  2. Oläsbar minimumVersion ⇒ fältet faller bort (redan i schema.ts). Alternativet — att tolka skräp som "oändligt högt" — hade spärrat alla användare på en felskrivning i Unleash.
  3. Ingen butiks-URL ⇒ ingen tvingande spärr. VER-04 kräver en fungerande väg till butiken. Saknas den mildras beslutet till update-recommended och degradedFrom: 'update-required' sätts, så att avvikelsen syns i telemetrin i stället för att bli en app utan utgång.

Butiks-URL:en är säkerhetskänslig

storeUrl kan komma från fjärrconfigen. En spärrskärm som inte går att avfärda, med en knapp som leder vart som helst, vore en perfekt nätfiskeyta. Därför valideras en fjärrsatt URL mot en allowlist som appen äger (DEFAULT_ALLOWED_STORE_HOSTS: apps.apple.com, itunes.apple.com, testflight.apple.com, play.google.com). Endast https, inga inbäddade uppgifter. En förkastad override faller tillbaka på den härledda URL:en och loggar store-url-rejected:<plattform>.

Cachestrategi

Ålder Källa Beteende
ttlSeconds cache ingen nätverkstrafik
maxAgeSeconds cache returneras direkt, revalidering i bakgrunden (stale-while-revalidate)
> maxAgeSeconds stale-cache används fortfarande — senast kända minimumVersion gäller
inget dokument none ingen spärr kan resas

Den tredje raden är hela poängen med fail-safe, inte fail-open: en app som varit offline i en månad respekterar fortfarande den senast kända gränsen. Den fjärde är dess motsats och lika medveten — utan data spärrar vi ingen.

Andra egenskaper som är testade: samtidiga hämtningar deduplicerar till en förfrågan · ett nätverksfel raderar aldrig en fungerande cache · en korrupt cache slängs och appen startar ändå · en klocka som hoppar bakåt ger inte negativ ålder · ett skrivfel i lagringen fäller inte hämtningen.

Tolerant schema

parseRemoteConfigDocument() förkastar bara det som inte ens är ett objekt. Allt annat degraderar fältvis med en varning: en trasig flagga tas bort, resten överlever; en nyare schemaVersion från servern bricker inte en äldre klient. En delvis trasig config ska ge en delvis fungerande app — inte en spärrad.

Feature flags

isEnabled() är synkron (flaggor läses i render), deny-by-default, och faller tillbaka på defaultFlags innan servern svarat. Varianter speglar Unleashs form ({ name, enabled, payload: { type, value } }) — vi hittar inte på ett eget format.

Filer

Fil Ansvar
src/semver.ts semver 2.0.0-parsning och -jämförelse
src/version-gate.ts VER-04/VER-05-beslutet
src/store.ts butiks-URL:er + allowlist
src/schema.ts tolerant parsning av configdokumentet
src/client.ts cache, stale-while-revalidate, flaggläsning
src/http-transport.ts valfri HTTP-adapter mot services/config
src/storage.ts lagringsadaptrar (minne, synkront KV)

Tester

cd packages/mobile-config
node --test        # 56 tester, inga beroenden, ingen npm install
tsc -p tsconfig.json

Kör från repo-roten: node --test "packages/mobile-config/**/*.test.ts". (Ett katalogargument — node --test packages/mobile-config — fungerar inte på Node 24: positionsargument tolkas som globmönster, och en katalog matchar bara sig själv.)

Kräver Node ≥ 22.18 för inbyggd typradering — testerna importerar .ts direkt. Node 20 kan inte köra dem.

Medvetet ogjort

  • Ej publicerad till https://git.siax.io/api/packages/sax3l/npm/.
  • Ingen exempelapp (MOB-13 kräver en i CI). Det hör till M2 och behöver app-generatorn.
  • services/config är inte byggd av detta paket — den ägs av M10 och en parallell session. Kontraktet som antas här: GET /v1/config?platform=…&appVersion=… som svarar med schema.ts-dokumentet.
  • Typkontroll av testfilerna kräver @types/node, som medvetet inte installerats i denna omgång. tsconfig.json täcker därför src/** — testerna är verifierade separat och är rena bortsett från saknade Node-typer.
  • Ingen AbortSignal-genomgång från anroparen till refresh(); timeouten ligger i HTTP-transporten.
Details
npm
2026-08-10 12:03:21 +00:00
38
UNLICENSED
latest
21 KiB
Assets (1)
Versions (2) View all
0.1.1 2026-08-10
0.1.0 2026-08-10