Skip to content

Commit 11cfc8d

Browse files
committed
Rewrite the prose without em-dashes across docs, comments and copy
1 parent f096238 commit 11cfc8d

12 files changed

Lines changed: 35 additions & 35 deletions

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Unreleased
44

55
- `appVersion` stays required here, while the Swift and Flutter SDKs now detect
6-
it. React Native exposes nothing that reads the host app's version — reaching
6+
it. React Native exposes nothing that reads the host app's version. Reaching
77
the bundle needs a native module, and this package having none is worth more
88
than saving a caller one argument. Documented rather than papered over.
99
- Removed the kill switch, following its removal from the protocol. Evaluation
@@ -16,8 +16,8 @@ First release.
1616

1717
- Force update, soft update, kill switch and maintenance mode, decided by the
1818
protocol's evaluation order and verified against the golden vectors.
19-
- Remote config values in the same signed payload no extra request.
19+
- Remote config values in the same signed payload, so there is no extra request.
2020
- Ed25519 verification of the exact response bytes, with SHA-512 wired for
21-
runtimes without `crypto.subtle` which is all of React Native.
21+
runtimes without `crypto.subtle`, which is all of React Native.
2222
- Signed cache, re-verified on read. AsyncStorage adapter, no dependency on it.
2323
- `RipstopProvider` with prebuilt walls, or `useRipstop()` and draw your own.

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
1010
</p>
1111

12-
<p align="center"><b>Remote config, update walls and maintenance mode for React Native — decided at the edge, verified on device.</b></p>
12+
<p align="center"><b>Remote config, update walls and maintenance mode for React Native. Decided at the edge, verified on device.</b></p>
1313

1414
## Installation
1515

1616
`@ripstop/react-native` is not on npm yet. Until it is, install straight from
17-
GitHub — the package builds itself on install:
17+
GitHub. The package builds itself on install:
1818

1919
```bash
2020
npm install github:ripstop-dev/ripstop-react-native
@@ -47,13 +47,13 @@ says otherwise, then shows the right wall.
4747

4848
## Why you still pass `appVersion`
4949

50-
The other Ripstop SDKs read the installed version themselves Swift from
51-
`CFBundleShortVersionString`, Flutter from `package_info_plus`. React Native
50+
The other Ripstop SDKs read the installed version themselves, Swift from
51+
`CFBundleShortVersionString` and Flutter from `package_info_plus`. React Native
5252
cannot. Nothing in the framework exposes the host app's version: `Platform.OS`
5353
and `Platform.Version` describe the operating system, and
5454
`Platform.constants.reactNativeVersion` describes React Native. Reading the
55-
bundle means a native module, and this package has none — see the installation
56-
note above, which is a promise worth more than saving you one argument.
55+
bundle means a native module, and this package has none. See the installation
56+
note above; that promise is worth more than saving you one argument.
5757

5858
So pass it, from whichever of these you already have:
5959

@@ -62,7 +62,7 @@ import DeviceInfo from 'react-native-device-info'; // DeviceInfo.getVersion()
6262
import Constants from 'expo-constants'; // Constants.expoConfig?.version
6363
```
6464

65-
Pass the version only `1.4.0`, not `1.4.0 (312)`. Build numbers are not part
65+
Pass the version only: `1.4.0`, not `1.4.0 (312)`. Build numbers are not part
6666
of a semantic version, and the rules are compared as semantic versions.
6767

6868
## Or draw your own
@@ -78,7 +78,7 @@ Pass `walls={false}` to the provider and nothing is rendered for you.
7878
## Storage
7979

8080
The cache is in-memory unless you give it somewhere to live. AsyncStorage is a
81-
separate package and the SDK will not add it to your app on your behalf — pass
81+
separate package and the SDK will not add it to your app on your behalf. Pass
8282
your existing instance through `asyncStorageAdapter` and the cache survives
8383
restarts.
8484

@@ -87,7 +87,7 @@ restarts.
8787
| Situation | What your app does |
8888
| --- | --- |
8989
| No network | Uses the last **signed** payload |
90-
| No network, no cache | `none` your app runs, unrestricted |
90+
| No network, no cache | `none`, so your app runs unrestricted |
9191
| Server returns 500, or times out | Cache, then normal |
9292
| Signature doesn't verify | Discarded. A forged payload can never wall your app |
9393
| Cache tampered with | Re-verified on read, so it grants nothing |
@@ -98,12 +98,12 @@ restarts.
9898
React Native doesn't have it. `@noble/ed25519` backs its SHA-512 with WebCrypto
9999
by default, so a naive integration verifies fine in every test and throws on the
100100
first real device. This package wires SHA-512 explicitly from `@noble/hashes`,
101-
and has a test that deletes `crypto.subtle` before importing anything because
101+
and has a test that deletes `crypto.subtle` before importing anything, because
102102
a test that runs on Node's fallback would pass whether or not the fix was there.
103103

104104
## Conformance
105105

106-
Every Ripstop SDK runs the same `vectors.json` version ordering, evaluation
106+
Every Ripstop SDK runs the same `vectors.json`: version ordering, evaluation
107107
order, snooze accounting, the fail-open state machine. `npm test` runs it here.
108108

109109
Full docs: **[ripstop.dev/docs/react-native](https://ripstop.dev/docs/react-native)**

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@ripstop/react-native",
33
"version": "0.1.0",
4-
"description": "Remote config, update walls and maintenance mode for React Native — signed at the edge, verified on device.",
4+
"description": "Remote config, update walls and maintenance mode for React Native. Signed at the edge, verified on device.",
55
"license": "MIT",
66
"repository": { "type": "git", "url": "git+https://github.com/ripstop-dev/ripstop-react-native.git" },
77
"homepage": "https://ripstop.dev/docs/react-native",

src/client.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export interface RipstopOptions {
2727
* bundle means a native module. This package has none, and that is worth
2828
* more than saving a caller one argument.
2929
*
30-
* The version only `1.4.0`, not `1.4.0 (312)`. Build numbers are not part
30+
* The version only: `1.4.0`, not `1.4.0 (312)`. Build numbers are not part
3131
* of a semantic version, and these are compared as semantic versions.
3232
*/
3333
appVersion: string;
@@ -186,8 +186,8 @@ export class Ripstop {
186186

187187
/**
188188
* Adopts a payload only if it still verifies. Cached payloads get the same
189-
* scrutiny as fresh ones localStorage is editable from the console, so
190-
* trusting it would make every wall a suggestion.
189+
* scrutiny as fresh ones, because localStorage is editable from the console
190+
* and trusting it would make every wall a suggestion.
191191
*/
192192
private async adopt(
193193
body: string,

src/evaluate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function evaluate(config: RipstopConfig, ctx: EvaluateContext): Decision
5151
const locale = ctx.locale ?? FALLBACK_LOCALE;
5252
const version = parseVersion(ctx.appVersion);
5353

54-
// 1. Maintenance `active` is server-evaluated at fetch time; starts_at/ends_at are display-only.
54+
// 1. Maintenance. `active` is server-evaluated at fetch time; starts_at/ends_at are display-only.
5555
const maintenance = config.maintenance;
5656
if (maintenance.active) {
5757
return {
@@ -65,7 +65,7 @@ export function evaluate(config: RipstopConfig, ctx: EvaluateContext): Decision
6565
};
6666
}
6767

68-
// 2–3. Force / soft need a platform entry and a parseable version; otherwise fail open.
68+
// 2–3. Force / soft need a platform entry and a parseable version; otherwise fail open.
6969
const entry = config.update[ctx.platform];
7070
if (entry === undefined || version === null) return { type: 'none' };
7171

src/storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Where the last signed payload and the snooze ledger live.
33
*
44
* The payload is stored *with* its signature and re-verified on read, so a
5-
* cached config carries exactly as much authority as a fresh one and no more.
5+
* cached config carries exactly as much authority as a fresh one, and no more.
66
* On the web this matters more than on mobile: localStorage is two keystrokes
77
* away in devtools, so a cache that were trusted would make a maintenance wall
88
* a polite request.

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* ~14 KB gzipped and would be the largest thing in a package whose whole point
66
* is to be small enough that nobody thinks twice about adding it. The server
77
* already guarantees the shape, the signature guarantees the bytes came from
8-
* the server, and anything unreadable falls open so a schema library here
8+
* the server, and anything unreadable falls open, so a schema library here
99
* would buy a nicer error message on a path that is already safe.
1010
*/
1111

src/verify.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* React Native has no `crypto.subtle`, so `@noble/ed25519` cannot fall back to
55
* WebCrypto for its SHA-512 the way it does in a browser. The hash is wired up
6-
* explicitly from `@noble/hashes` — without this the SDK would throw on the
6+
* explicitly from `@noble/hashes`. Without this the SDK would throw on the
77
* first verification, on device, in production, and nowhere in a JSDOM test.
88
*
99
* The signature covers the raw response body, so verification happens before
@@ -17,7 +17,7 @@ import { sha512 } from '@noble/hashes/sha2';
1717
//
1818
// `@noble/ed25519` ships an async SHA-512 backed by `crypto.subtle`, which is
1919
// exactly what React Native does not have. Left alone, the first signature
20-
// check would throw on a real device and never in a Node test so both the
20+
// check would throw on a real device and never in a Node test, so both the
2121
// sync and async hooks are pointed at `@noble/hashes` instead.
2222
// The copy also normalises the backing buffer: noble's types require a plain
2323
// `ArrayBuffer`, and a hash may return a view onto a shared one.
@@ -39,9 +39,9 @@ export class SignatureVerifier {
3939
constructor(private readonly keys: Record<string, string>) {}
4040

4141
/**
42-
* True only for a genuine signature by the named pinned key. Every failure
43-
* unknown key, malformed base64, wrong length, bad signature — is a plain
44-
* false, and callers then fall back to cache.
42+
* True only for a genuine signature by the named pinned key. Every failure
43+
* is a plain false: an unknown key, malformed base64, the wrong length, a
44+
* bad signature. Callers then fall back to cache.
4545
*/
4646
async verify(body: string, signature: string, keyId: string): Promise<boolean> {
4747
const encoded = this.keys[keyId];

test/client.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/**
2-
* What the client promises when things go wrongthe only time anybody finds
3-
* out whether a config SDK was written carefully.
2+
* What the client promises when things go wrong, which is the only time
3+
* anybody finds out whether a config SDK was written carefully.
44
*
55
* These sign with a real key pair and stub `fetch`. Importing the client pulls
6-
* in `verify.ts`, which is where the SHA-512 hook is installed so these also
6+
* in `verify.ts`, which is where the SHA-512 hook is installed, so these also
77
* prove that verification works without `crypto.subtle`, which is the thing
88
* React Native lacks and a browser hides.
99
*/
@@ -122,7 +122,7 @@ describe('the client', () => {
122122

123123
it('has no opinion about a version it cannot read', async () => {
124124
// `appVersion` is required here because React Native will not tell us the
125-
// installed version, which puts the value in the caller's hands so the
125+
// installed version, which puts the value in the caller's hands, so the
126126
// common mistakes have to fail open rather than wall somebody. A display
127127
// string with the build number in it is the one people reach for.
128128
const { impl } = server(config());

test/vectors.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"version": 1,
3-
"notes": "Golden vectors — every implementation (TS reference + all SDKs) must pass all cases. `compare` expects sign of compare(a,b); harnesses must also assert compare(b,a) === -expect. `evaluate` cases: config = top-level replacement of `patch` keys over `base_config` (no deep merge); `expect` is a subset match listed fields must equal, extra fields in the actual decision are allowed. `config_source` covers the fail-open state machine. Adding a vector is feat:, changing one is an ADR.",
3+
"notes": "Golden vectors. Every implementation (TS reference + all SDKs) must pass all cases. `compare` expects sign of compare(a,b); harnesses must also assert compare(b,a) === -expect. `evaluate` cases: config = top-level replacement of `patch` keys over `base_config` (no deep merge); `expect` is a subset match, so listed fields must equal, and extra fields in the actual decision are allowed. `config_source` covers the fail-open state machine. Adding a vector is feat:, changing one is an ADR.",
44
"base_config": {
55
"v": 1,
66
"app": "app_test",

0 commit comments

Comments
 (0)