@cortexkit/claustrum-client 0.15.0 → 0.16.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 +33 -1
- package/dist/enrollment.d.ts +7 -0
- package/dist/enrollment.js +13 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -76,6 +76,11 @@ copy. One behaviour reaches callers: while the vault is restarting or refusing r
|
|
|
76
76
|
opens as retryable, a call now keeps retrying for up to 90 s (paced, with jitter) instead
|
|
77
77
|
of 30 s. Give every vault call on a latency-sensitive path its own timeout.
|
|
78
78
|
|
|
79
|
+
**Changed in 0.16.0:** the dependency is now `@cortexkit/subc-client` ^0.24.0.
|
|
80
|
+
The SDK negotiates FIFO request/watch windows and retries only daemon-origin
|
|
81
|
+
`route_busy` refusals within the request deadline. Claustrum adds no busy retry;
|
|
82
|
+
older daemons keep the SDK's previous behavior.
|
|
83
|
+
|
|
79
84
|
## Reading credential material
|
|
80
85
|
|
|
81
86
|
The wire payload is opaque bytes. `getCredential(handle, minTtlMs?)` and
|
|
@@ -161,10 +166,37 @@ for (;;) {
|
|
|
161
166
|
}
|
|
162
167
|
```
|
|
163
168
|
|
|
169
|
+
## Enrollment
|
|
170
|
+
|
|
171
|
+
Use `newEnrollmentSecret()` to prepare an enrollment proposal. It generates 32
|
|
172
|
+
random bytes as exactly 64 lowercase hex characters, plus `requestSecretHash`:
|
|
173
|
+
the lowercase hex SHA-256 of the **32 decoded bytes**, not of the UTF-8 hex text.
|
|
174
|
+
`enrollmentSecretHash(requestSecret)` recomputes the hash of a persisted secret
|
|
175
|
+
and refuses anything other than exactly 64 lowercase hex characters.
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
import { ClaustrumClient, newEnrollmentSecret } from '@cortexkit/claustrum-client'
|
|
179
|
+
|
|
180
|
+
const client = await ClaustrumClient.connect()
|
|
181
|
+
const { requestSecret, requestSecretHash } = newEnrollmentSecret()
|
|
182
|
+
// Persist the secret privately before proposing so a crash can recover the poll.
|
|
183
|
+
await persistRequestSecret(requestSecret)
|
|
184
|
+
const { requestId } = await client.enrollPropose({ name: 'consumer', requestSecretHash })
|
|
185
|
+
await persistRequestId(requestId)
|
|
186
|
+
// After operator approval, poll with the original secret, not its hash.
|
|
187
|
+
const outcome = await client.enrollPoll({ requestId, requestSecret })
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The persistence functions above are caller-provided. Re-proposing the same name
|
|
191
|
+
with the same persisted secret/hash recovers the request id after a lost reply.
|
|
192
|
+
Only `pending` means poll again; an approved outcome returns the token once, so
|
|
193
|
+
persist it with `writeEnrollmentTokenFile` before using it. Never log the request
|
|
194
|
+
secret or token.
|
|
195
|
+
|
|
164
196
|
## Private files and Windows support
|
|
165
197
|
|
|
166
198
|
Enrollment tokens support Windows as well as Unix. The client uses
|
|
167
|
-
`@cortexkit/store` 0.2.
|
|
199
|
+
`@cortexkit/store` 0.2.3 or newer: exclusive private creation
|
|
168
200
|
protects files before any secret bytes are written, and atomic replacement keeps
|
|
169
201
|
that protection. Unix files use mode 0600 and new directories use 0700. On Windows,
|
|
170
202
|
the store's `@cortexkit/private-files` native module creates owner-only ACLs and the
|
package/dist/enrollment.d.ts
CHANGED
|
@@ -3,5 +3,12 @@ export type EnrollmentTokenFile = {
|
|
|
3
3
|
token: string;
|
|
4
4
|
token_generation: number;
|
|
5
5
|
};
|
|
6
|
+
/** Hash the 32 decoded bytes, not the UTF-8 text of the hex request secret. */
|
|
7
|
+
export declare function enrollmentSecretHash(requestSecret: string): string;
|
|
8
|
+
/** Mint an enrollment request secret and the hash to send with the proposal. */
|
|
9
|
+
export declare function newEnrollmentSecret(): {
|
|
10
|
+
requestSecret: string;
|
|
11
|
+
requestSecretHash: string;
|
|
12
|
+
};
|
|
6
13
|
export declare function createEnrollmentWriter(checkPath?: typeof checkPrivatePath): (path: string, value: EnrollmentTokenFile) => Promise<void>;
|
|
7
14
|
export declare const writeEnrollmentTokenFile: (path: string, value: EnrollmentTokenFile) => Promise<void>;
|
package/dist/enrollment.js
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { createPrivateFile } from '@cortexkit/store';
|
|
2
2
|
import { checkPrivatePath, createPrivateParents, notPrivate, privateCreationCode } from './private-path.js';
|
|
3
|
-
import { randomBytes } from 'node:crypto';
|
|
3
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
4
4
|
import { open, rename, unlink } from 'node:fs/promises';
|
|
5
5
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
6
6
|
const TOKEN_RE = /^[0-9a-f]{64}$/;
|
|
7
|
+
/** Hash the 32 decoded bytes, not the UTF-8 text of the hex request secret. */
|
|
8
|
+
export function enrollmentSecretHash(requestSecret) {
|
|
9
|
+
if (typeof requestSecret !== 'string' || requestSecret.length !== 64 || !TOKEN_RE.test(requestSecret)) {
|
|
10
|
+
throw new Error('enrollment request secret must be exactly 64 lowercase hex characters');
|
|
11
|
+
}
|
|
12
|
+
return createHash('sha256').update(Buffer.from(requestSecret, 'hex')).digest('hex');
|
|
13
|
+
}
|
|
14
|
+
/** Mint an enrollment request secret and the hash to send with the proposal. */
|
|
15
|
+
export function newEnrollmentSecret() {
|
|
16
|
+
const requestSecret = randomBytes(32).toString('hex');
|
|
17
|
+
return { requestSecret, requestSecretHash: enrollmentSecretHash(requestSecret) };
|
|
18
|
+
}
|
|
7
19
|
function validateTokenFile(value) {
|
|
8
20
|
if (!TOKEN_RE.test(value.token))
|
|
9
21
|
throw new Error('enrollment token must be exactly 64 lowercase hex characters');
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { detectClaustrumConnection, getDefaultClaustrumConnectionPath, resolveClaustrumConnectionPath, type ClaustrumDetection, type ClaustrumEndpoint, } from './detect.js';
|
|
2
2
|
export { storeIdentity, storageFingerprint } from './identity.js';
|
|
3
|
-
export { writeEnrollmentTokenFile, type EnrollmentTokenFile, } from './enrollment.js';
|
|
3
|
+
export { enrollmentSecretHash, newEnrollmentSecret, writeEnrollmentTokenFile, type EnrollmentTokenFile, } from './enrollment.js';
|
|
4
4
|
export { ClaustrumCredentialError, credentialErrorAction, ERROR_CLASS_WIRE_SET, type ClaustrumCredentialErrorAction, type ClaustrumCredentialErrorClass, } from './errors.js';
|
|
5
5
|
export { ClaustrumClient, type ClaustrumClientOptions, type ClaustrumConnector, type ClaustrumReporterSource, type CredentialStatus, type EnrollmentPollOutcome, type ScopedGrantTuple, type ScopedInventory, type ScopedInventoryRow, type ServedCredential, type ServedCredentialBytes, } from './wire.js';
|
|
6
6
|
export { ScopedWatchError, type ScopedWatch, type ScopedWatchNotice, type ScopedWatchOptions, type ScopedWatchOutcome, } from './watch.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { detectClaustrumConnection, getDefaultClaustrumConnectionPath, resolveClaustrumConnectionPath, } from './detect.js';
|
|
2
2
|
export { storeIdentity, storageFingerprint } from './identity.js';
|
|
3
|
-
export { writeEnrollmentTokenFile, } from './enrollment.js';
|
|
3
|
+
export { enrollmentSecretHash, newEnrollmentSecret, writeEnrollmentTokenFile, } from './enrollment.js';
|
|
4
4
|
export { ClaustrumCredentialError, credentialErrorAction, ERROR_CLASS_WIRE_SET, } from './errors.js';
|
|
5
5
|
export { ClaustrumClient, } from './wire.js';
|
|
6
6
|
export { ScopedWatchError, } from './watch.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/claustrum-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cortexkit/store": "^0.2.
|
|
31
|
-
"@cortexkit/subc-client": "^0.
|
|
30
|
+
"@cortexkit/store": "^0.2.3",
|
|
31
|
+
"@cortexkit/subc-client": "^0.24.0"
|
|
32
32
|
}
|
|
33
33
|
}
|