Skip to content

Commit 1824031

Browse files
committed
Rewrite the prose without em-dashes across docs, comments and copy
1 parent 20391cd commit 1824031

12 files changed

Lines changed: 30 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ First release.
1212

1313
- Force update, soft update and maintenance mode, decided by the protocol's
1414
evaluation order and verified against the golden vectors.
15-
- Remote config values in the same signed payload no extra request.
15+
- Remote config values in the same signed payload, so there is no extra request.
1616
- Ed25519 verification of the exact response bytes, with pinned keys and
1717
`key_id` rotation.
1818
- Signed cache in localStorage, re-verified on read.

README.md

Lines changed: 12 additions & 12 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 web apps — signed at the edge, verified in the browser, 6.5 KB gzipped.</b></p>
12+
<p align="center"><b>Remote config, update walls and maintenance mode for web apps. Signed at the edge, verified in the browser, 6.5 KB gzipped.</b></p>
1313

1414
## Installation
1515

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

1919
```bash
2020
npm install github:ripstop-dev/ripstop-web
@@ -53,12 +53,12 @@ switch (decision.type) {
5353

5454
`appVersion` is explicit here and always will be. The Swift and Flutter SDKs
5555
read the installed version from the bundle, but a browser has no bundle and no
56-
installed version to read — the only thing that knows which build is running is
56+
installed version to read. The only thing that knows which build is running is
5757
the build itself, so it has to hand the string over. Every bundler can: Vite's
5858
`define`, webpack's `DefinePlugin`, or an env var read at build time.
5959

6060
Pass a semantic version, not a commit SHA. The rules are ordered as semantic
61-
versions, and anything that is not one is treated as no opinion which lets the
61+
versions, and anything that is not one is treated as no opinion, which lets the
6262
app run rather than walling it, but also means your rules do nothing.
6363

6464
## What `force` means on the web
@@ -70,7 +70,7 @@ response is usually `location.reload()`.
7070

7171
That is also why the web SDK ships no prebuilt walls. On mobile, a full-screen
7272
update wall is the same shape in every app. On the web it is a banner, a modal,
73-
or a route entirely yours. You get the decision and the copy you wrote in the
73+
or a route, entirely yours. You get the decision and the copy you wrote in the
7474
panel; the markup is your business.
7575

7676
## Remote config
@@ -83,15 +83,15 @@ const checkout = ripstop.value('checkout_enabled', true);
8383
const limit = ripstop.value('upload_limit', 10);
8484
```
8585

86-
Always pass a fallback. On a first load with no network there is no payload yet
87-
— that is the fail-open path working as intended.
86+
Always pass a fallback. On a first load with no network there is no payload
87+
yet. That is the fail-open path working as intended.
8888

8989
## API
9090

9191
| | Default | |
9292
| --- | --- | --- |
93-
| `apiKey` | | Your app's public SDK key. Safe to ship |
94-
| `appVersion` | | The build you are running; rules evaluate against it |
93+
| `apiKey` | required | Your app's public SDK key. Safe to ship |
94+
| `appVersion` | required | The build you are running; rules evaluate against it |
9595
| `locale` | `en` | Which wall copy to resolve; falls back to `en` per key |
9696
| `minFetchInterval` | 6 hours | How long a payload is fresh enough to skip the network |
9797
| `timeoutMs` | 5000 | Fetch budget. After that, cache |
@@ -104,7 +104,7 @@ Always pass a fallback. On a first load with no network there is no payload yet
104104
| Situation | What your app does |
105105
| --- | --- |
106106
| Network unavailable | Uses the last **signed** payload from localStorage |
107-
| No network, no cache | `none` your app runs, unrestricted |
107+
| No network, no cache | `none`, so your app runs unrestricted |
108108
| Edge returns 5xx, or times out | Cache, then normal |
109109
| Signature doesn't verify | Discarded. A forged payload can never wall your app |
110110
| localStorage edited in devtools | Re-verified on read, so it grants nothing |
@@ -122,7 +122,7 @@ simply doesn't persist a cache.
122122

123123
## Conformance
124124

125-
Every Ripstop SDK runs the same `vectors.json` version ordering, evaluation
125+
Every Ripstop SDK runs the same `vectors.json`: version ordering, evaluation
126126
order, message fallback, snooze accounting, the fail-open state machine.
127127
`npm test` runs it here. If this package and the reference implementation ever
128128
disagree about a single comparison, CI goes red.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@ripstop/web",
33
"version": "0.1.0",
4-
"description": "Remote config, update walls and maintenance mode for web apps — signed at the edge, verified in the browser.",
4+
"description": "Remote config, update walls and maintenance mode for web apps. Signed at the edge, verified in the browser.",
55
"license": "MIT",
66
"type": "module",
77
"repository": {

src/client.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* The client: fetch, verify, cache, decide.
33
*
4-
* Web differs from mobile in one way that shapes everything here there is no
4+
* Web differs from mobile in one way that shapes everything here: there is no
55
* app store and no "old build in the field", because a reload gets the latest
66
* code. So `force` on web is not about a binary being stale, it is about a tab
77
* that has been open for three days while you shipped a breaking change. The
@@ -178,8 +178,8 @@ export class Ripstop {
178178

179179
/**
180180
* Adopts a payload only if it still verifies. Cached payloads get the same
181-
* scrutiny as fresh ones localStorage is editable from the console, so
182-
* trusting it would make every wall a suggestion.
181+
* scrutiny as fresh ones, because localStorage is editable from the console
182+
* and trusting it would make every wall a suggestion.
183183
*/
184184
private async adopt(
185185
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/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Ripstop for the web remote config, update walls and maintenance mode,
2+
* Ripstop for the web: remote config, update walls and maintenance mode,
33
* signed at the edge and verified in the browser.
44
*
55
* ```ts

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 every wall a
88
* 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: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* silently degrades on older Safari is worse than one that carries 4 KB.
77
*
88
* The signature covers the raw response body, so verification happens before
9-
* anything is parsed `JSON.parse` then `JSON.stringify` would produce
9+
* anything is parsed. `JSON.parse` then `JSON.stringify` would produce
1010
* different bytes for the same document and reject payloads that were genuine.
1111
*/
1212
import { verifyAsync } from '@noble/ed25519';
@@ -22,9 +22,9 @@ export class SignatureVerifier {
2222
constructor(private readonly keys: Record<string, string>) {}
2323

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

test/client.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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`, so the verification path is
66
* exercised for real. A verifier that is mocked in tests is a verifier nobody

0 commit comments

Comments
 (0)