@infinitetoken/lumber-kit 0.5.2 → 0.7.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/README.md +26 -5
- package/contract/README.md +21 -0
- package/contract/schema.json +2273 -0
- package/contract/vectors.json +180 -0
- package/dist/index.d.mts +114 -5
- package/dist/index.d.ts +114 -5
- package/dist/index.js +58 -9
- package/dist/index.mjs +52 -9
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ import { LogLevel, LogRecord, LogEncrypted, LogPayload, LogsQuery } from '@infin
|
|
|
50
50
|
| `PUSH_OFF` | constant | A push threshold one past Fatal (5): log pushes off |
|
|
51
51
|
| `PushThreshold` | type | A `LogLevel` or `PUSH_OFF`, stored as a preference's `minimumLevel` |
|
|
52
52
|
| `normalizePushThreshold` | function | A threshold from any stored or sent value: past Fatal is off, not a number is Warn |
|
|
53
|
-
| `PushData` | type | The `data` each push type carries (`log`, `note`, `device_link`, `key_check`, `key_waiting`, `keys_shared`) |
|
|
53
|
+
| `PushData` | type | The `data` each push type carries (`log`, `note`, `device_link`, `device_link_answered`, `key_check`, `key_waiting`, `keys_shared`) |
|
|
54
54
|
| `parsePushData` | function | A push's data as `PushData`, or `null` for data no Lumber push sends |
|
|
55
55
|
|
|
56
56
|
### Socket events
|
|
@@ -100,6 +100,10 @@ import { LogLevel, LogRecord, LogEncrypted, LogPayload, LogsQuery } from '@infin
|
|
|
100
100
|
| `AppKeyUpsertBody` | interface | Body of PUT /apps/:id/keys/:userId |
|
|
101
101
|
| `KeyPin` | interface | An account key a user accepted for someone, with its MAC |
|
|
102
102
|
| `HolderKeyCheck`, `ClaimantKeyCheck`, `KeyCheckResult` | interfaces | A key check as the holder and the person being confirmed read it |
|
|
103
|
+
| `DeviceLinkCreateBody`, `DeviceLinkCreatedRecord` | interfaces | POST /device-links: a new device asking for the account key, and its answer |
|
|
104
|
+
| `DeviceLinkRecord`, `DeviceLinkApproveBody` | interfaces | A link request as the new device polls it (the exchange's first message once a code is shown, then the account key and the tag proving a device that showed the code sent it), and the approval that carries them |
|
|
105
|
+
| `PendingDeviceLink` | interface | A link request as a device holding the account key reads it, to show its code and finish it |
|
|
106
|
+
| `DeviceLinkStatus`, `DeviceLinkPlatform` | types | `pending`, `approved`, `denied` or `failed` (a code that didn't match); what the request comes from |
|
|
103
107
|
|
|
104
108
|
### Colors
|
|
105
109
|
|
|
@@ -121,6 +125,19 @@ import { LogLevel, LogRecord, LogEncrypted, LogPayload, LogsQuery } from '@infin
|
|
|
121
125
|
|
|
122
126
|
A plugin sends only the token to the API (`Authorization: Bearer <token>`) and encrypts with the rest, so the encryption key never leaves it.
|
|
123
127
|
|
|
128
|
+
### Plugins
|
|
129
|
+
|
|
130
|
+
| Export | Kind | Purpose |
|
|
131
|
+
|--------|------|---------|
|
|
132
|
+
| `LogIngestBody` | interface | `POST /logs`' body: `{ level, encrypted }` |
|
|
133
|
+
| `LogData` | interface | What a log call takes beside its message: `requestId`, `traceId`, `context`, `metadata` and any other keys |
|
|
134
|
+
| `buildLogPayload` | function | The `LogPayload` a log call encrypts, from its level, message, data and the plugin's automatic context |
|
|
135
|
+
| `DEFAULT_API_ENDPOINT` | constant | `https://api.lumber.infinitetoken.com` |
|
|
136
|
+
| `LOG_KEY_VERSION` | constant | `LogEncrypted`'s `keyVersion` (1) |
|
|
137
|
+
| `logDelivery` | object | Attempts, retry delays and the pause after a 429 |
|
|
138
|
+
| `logDeliveryOutcome` | function | `sent`, `retry`, `drop` or `pause` for a `POST /logs` status (null for a network error) |
|
|
139
|
+
| `logRetryDelayMs` | function | The wait after a log's nth failed attempt: 1s, 2s, 4s, up to 30s |
|
|
140
|
+
|
|
124
141
|
## Wire format
|
|
125
142
|
|
|
126
143
|
All log content is E2E encrypted before leaving the client. `LogRecord` contains only:
|
|
@@ -131,14 +148,14 @@ All log content is E2E encrypted before leaving the client. `LogRecord` contains
|
|
|
131
148
|
createdAt: string // ISO 8601
|
|
132
149
|
updatedAt: string // ISO 8601
|
|
133
150
|
appId: string
|
|
134
|
-
encrypted: LogEncrypted // opaque
|
|
151
|
+
encrypted: LogEncrypted // opaque to the server, which can't read it
|
|
135
152
|
}
|
|
136
153
|
```
|
|
137
154
|
|
|
138
155
|
`LogEncrypted` uses AES-256-GCM:
|
|
139
|
-
- `nonce
|
|
140
|
-
- `payload
|
|
141
|
-
- `keyVersion
|
|
156
|
+
- `nonce`: base64(random IV, 12 bytes)
|
|
157
|
+
- `payload`: base64(authTag[16 bytes] + ciphertext)
|
|
158
|
+
- `keyVersion`: always `1` for the current format; changes are semver major
|
|
142
159
|
|
|
143
160
|
The plaintext shape inside `payload` is `LogPayload`:
|
|
144
161
|
|
|
@@ -153,6 +170,10 @@ The plaintext shape inside `payload` is `LogPayload`:
|
|
|
153
170
|
}
|
|
154
171
|
```
|
|
155
172
|
|
|
173
|
+
## Other languages
|
|
174
|
+
|
|
175
|
+
TypeScript can't be imported from Python or Go, so the kit ships its contract in `contract/`: a JSON Schema of every exported type (`schema.json`, generated from the TypeScript by `npm run contract`) and known answers (`vectors.json`) for API keys, AES-256-GCM, payloads and delivery, which the kit's own tests check against its code. Lumber-Python and Lumber-Go test against a pinned copy. See `contract/README.md`.
|
|
176
|
+
|
|
156
177
|
## const enum and Babel consumers
|
|
157
178
|
|
|
158
179
|
`LogLevel` is a TypeScript `const enum`. TypeScript consumers have values inlined at compile time (zero runtime overhead).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Lumber's contract
|
|
2
|
+
|
|
3
|
+
The shapes and known answers every Lumber client is tested against, whatever its language. Lumber-Kit's TypeScript is the source: these files are generated from it or checked against it by the kit's own tests, and they ship in the npm package, so a client pins them by the kit's version.
|
|
4
|
+
|
|
5
|
+
- `schema.json`: a JSON Schema (draft-07) of every type the kit exports, generated by `npm run contract`. A plugin sends `LogIngestBody` to `POST /logs` and encrypts a `LogPayload` into its `encrypted`. `LogPayload` allows no other keys, so a misspelled field (`request_id`) fails validation rather than going missing in the app.
|
|
6
|
+
- `vectors.json`: known answers.
|
|
7
|
+
- `constants`: the default endpoint, ingestion path, key version, key, nonce and tag sizes, log levels and the delivery policy.
|
|
8
|
+
- `apiKeys`: how an API key (`<token>.<encryptionKey>`) splits.
|
|
9
|
+
- `encryption`: AES-256-GCM with a fixed key and nonce, so a plugin's encryption has to give these exact bytes (`payload` is base64 of the 16-byte tag and then the ciphertext, `nonce` the 12-byte IV).
|
|
10
|
+
- `payloads`: the plaintext a log call builds from its level, message, data and the plugin's automatic context.
|
|
11
|
+
- `deliveryOutcomes` and `retryDelaysMs`: what each answer from `POST /logs` means, and how long to wait after each failure.
|
|
12
|
+
|
|
13
|
+
## In another language
|
|
14
|
+
|
|
15
|
+
Copy this folder into the client's tests at a pinned kit version, and test every vector against the client's own code. The kit's version is the contract's: when the kit changes a shape, the new version's files fail the client's tests until it catches up.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
curl -sL https://registry.npmjs.org/@infinitetoken/lumber-kit/-/lumber-kit-0.7.0.tgz | tar -xz --strip-components=1 package/contract
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Lumber-Python (`scripts/sync_contract.py`) and Lumber-Go (`scripts/sync-contract.sh`) each have a script that does this, and their CI fails when the copy differs from the pinned version's. Lumber-Node reads the contract straight from its installed kit (`@infinitetoken/lumber-kit/contract/vectors.json`).
|