@fungi.computer/ear-tag 0.0.0-stage → 0.0.1

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.
@@ -0,0 +1,191 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/ear-tag**](README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/ear-tag](README.md) / grants
8
+
9
+ # grants
10
+
11
+ ## Classes
12
+
13
+ ### GrantsDefinitionError
14
+
15
+ Rejected when a host's capability vocabulary violates `defineGrants`'
16
+ invariants.
17
+
18
+ This error retains neither the rejected definition nor a foreign cause.
19
+
20
+ #### Extends
21
+
22
+ - `Error`
23
+
24
+ #### Constructors
25
+
26
+ ##### Constructor
27
+
28
+ ```ts
29
+ new GrantsDefinitionError(): GrantsDefinitionError;
30
+ ```
31
+
32
+ Creates a fresh bounded definition error.
33
+
34
+ ###### Returns
35
+
36
+ [`GrantsDefinitionError`](#grantsdefinitionerror)
37
+
38
+ ###### Overrides
39
+
40
+ ```ts
41
+ Error.constructor;
42
+ ```
43
+
44
+ #### Properties
45
+
46
+ ##### name
47
+
48
+ ```ts
49
+ readonly name: "GrantsDefinitionError" = "GrantsDefinitionError";
50
+ ```
51
+
52
+ Stable public error name.
53
+
54
+ ###### Overrides
55
+
56
+ ```ts
57
+ Error.name;
58
+ ```
59
+
60
+ ## Type Aliases
61
+
62
+ ### GrantTargets
63
+
64
+ ```ts
65
+ type GrantTargets =
66
+ | Readonly<{
67
+ kind: "all";
68
+ }>
69
+ | Readonly<{
70
+ kind: "selected";
71
+ ids: readonly string[];
72
+ }>;
73
+ ```
74
+
75
+ How a grant's capability reaches resources.
76
+
77
+ ---
78
+
79
+ ### Grant
80
+
81
+ ```ts
82
+ type Grant<Capability> = Readonly<{
83
+ capability: Capability;
84
+ targets: GrantTargets;
85
+ }>;
86
+ ```
87
+
88
+ One capability bound to the resources it may act on.
89
+
90
+ #### Type Parameters
91
+
92
+ | Type Parameter | Default type |
93
+ | ------------------------------- | ------------ |
94
+ | `Capability` _extends_ `string` | `string` |
95
+
96
+ ---
97
+
98
+ ### Scope
99
+
100
+ ```ts
101
+ type Scope<Capability> = Readonly<{
102
+ grants: readonly Grant<Capability>[];
103
+ }>;
104
+ ```
105
+
106
+ The bounded authority one key carries: 1 to 64 grants.
107
+
108
+ #### Type Parameters
109
+
110
+ | Type Parameter | Default type |
111
+ | ------------------------------- | ------------ |
112
+ | `Capability` _extends_ `string` | `string` |
113
+
114
+ ---
115
+
116
+ ### GrantVocabulary
117
+
118
+ ```ts
119
+ type GrantVocabulary<Capability> = Readonly<{
120
+ capabilityNameSchema: z.ZodType<Capability>;
121
+ grantSchema: z.ZodType<Grant<Capability>>;
122
+ scopeSchema: z.ZodType<Scope<Capability>>;
123
+ canonicalGrants: (grants) => readonly Grant<Capability>[];
124
+ grantsAllow: (grants, capability, resourceId?) => boolean;
125
+ grantsList: (grants, capability) => boolean;
126
+ isSubset: (child, parent) => boolean;
127
+ }>;
128
+ ```
129
+
130
+ Zod schemas and grant operations closed over one host's capability vocabulary.
131
+
132
+ #### Type Parameters
133
+
134
+ | Type Parameter |
135
+ | ------------------------------- |
136
+ | `Capability` _extends_ `string` |
137
+
138
+ ---
139
+
140
+ ### GrantsDefinition
141
+
142
+ ```ts
143
+ type GrantsDefinition<Capability> = Readonly<{
144
+ capabilities: Capability;
145
+ implies?: Readonly<
146
+ Partial<Record<Capability[number], readonly Capability[number][]>>
147
+ >;
148
+ }>;
149
+ ```
150
+
151
+ A host's capability vocabulary and its optional implied-capability classes.
152
+
153
+ #### Type Parameters
154
+
155
+ | Type Parameter |
156
+ | ----------------------------------------------------------- |
157
+ | `Capability` _extends_ readonly \[`string`, `...string[]`\] |
158
+
159
+ ## Functions
160
+
161
+ ### defineGrants()
162
+
163
+ ```ts
164
+ function defineGrants<Capability>(
165
+ definition,
166
+ ): GrantVocabulary<Capability[number]>;
167
+ ```
168
+
169
+ Declares one host's capability vocabulary and the zod schemas and grant
170
+ operations closed over it.
171
+
172
+ #### Type Parameters
173
+
174
+ | Type Parameter |
175
+ | ------------------------------------------------------ |
176
+ | `Capability` _extends_ readonly \[`string`, `string`\] |
177
+
178
+ #### Parameters
179
+
180
+ | Parameter | Type |
181
+ | ------------ | ------------------------------------------------------- |
182
+ | `definition` | [`GrantsDefinition`](#grantsdefinition)\<`Capability`\> |
183
+
184
+ #### Returns
185
+
186
+ [`GrantVocabulary`](#grantvocabulary)\<`Capability`\[`number`\]\>
187
+
188
+ #### Throws
189
+
190
+ [GrantsDefinitionError](#grantsdefinitionerror) When the vocabulary repeats a
191
+ capability, or `implies` names a capability outside it.
@@ -0,0 +1,100 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/ear-tag**](README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/ear-tag](README.md) / index
8
+
9
+ # index
10
+
11
+ ## Type Aliases
12
+
13
+ ### GenerateKeyOptions
14
+
15
+ ```ts
16
+ type GenerateKeyOptions = Readonly<{
17
+ length?: number;
18
+ prefix?: string;
19
+ }>;
20
+ ```
21
+
22
+ Options for generating a bearer key.
23
+
24
+ ---
25
+
26
+ ### GeneratedKey
27
+
28
+ ```ts
29
+ type GeneratedKey = Readonly<{
30
+ digest: string;
31
+ key: string;
32
+ }>;
33
+ ```
34
+
35
+ A newly generated bearer key and the digest safe to retain in storage.
36
+
37
+ ## Functions
38
+
39
+ ### generateKey()
40
+
41
+ ```ts
42
+ function generateKey(options?): string;
43
+ ```
44
+
45
+ Generate a cryptographically random bearer key.
46
+
47
+ #### Parameters
48
+
49
+ | Parameter | Type |
50
+ | --------- | ------------------------------------------- |
51
+ | `options` | [`GenerateKeyOptions`](#generatekeyoptions) |
52
+
53
+ #### Returns
54
+
55
+ `string`
56
+
57
+ ---
58
+
59
+ ### hashKey()
60
+
61
+ ```ts
62
+ function hashKey(key): Promise<string>;
63
+ ```
64
+
65
+ Hash a bearer key with Worker-compatible Web Crypto.
66
+
67
+ #### Parameters
68
+
69
+ | Parameter | Type |
70
+ | --------- | -------- |
71
+ | `key` | `string` |
72
+
73
+ #### Returns
74
+
75
+ `Promise`\<`string`\>
76
+
77
+ ---
78
+
79
+ ### generateKeyAndHash()
80
+
81
+ ```ts
82
+ function generateKeyAndHash(options?): Promise<
83
+ Readonly<{
84
+ digest: string;
85
+ key: string;
86
+ }>
87
+ >;
88
+ ```
89
+
90
+ Generate a bearer key and the digest its owner should persist.
91
+
92
+ #### Parameters
93
+
94
+ | Parameter | Type |
95
+ | --------- | ------------------------------------------- |
96
+ | `options` | [`GenerateKeyOptions`](#generatekeyoptions) |
97
+
98
+ #### Returns
99
+
100
+ `Promise`\<`Readonly`\<\{ `digest`: `string`; `key`: `string`; \}\>\>
@@ -0,0 +1,31 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/ear-tag**](README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/ear-tag](README.md) / keys-node
8
+
9
+ # keys-node
10
+
11
+ ## Functions
12
+
13
+ ### fromNodeSqlite()
14
+
15
+ ```ts
16
+ function fromNodeSqlite(database): KeySql;
17
+ ```
18
+
19
+ Adapt a caller-owned `node:sqlite` database to the `KeySql` port
20
+ `createKeyStore` expects, for hosts that run outside a Durable Object. The
21
+ caller retains the database's lifetime.
22
+
23
+ #### Parameters
24
+
25
+ | Parameter | Type |
26
+ | ---------- | -------------- |
27
+ | `database` | `DatabaseSync` |
28
+
29
+ #### Returns
30
+
31
+ [`KeySql`](keys.md#keysql)
@@ -0,0 +1,406 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/ear-tag**](README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/ear-tag](README.md) / keys
8
+
9
+ # keys
10
+
11
+ ## Type Aliases
12
+
13
+ ### KeySqlValue
14
+
15
+ ```ts
16
+ type KeySqlValue = string | number | null;
17
+ ```
18
+
19
+ One bound SQL value a key store statement may carry.
20
+
21
+ ---
22
+
23
+ ### KeySqlRow
24
+
25
+ ```ts
26
+ type KeySqlRow = Readonly<Record<string, KeySqlValue>>;
27
+ ```
28
+
29
+ One materialized SQL row, keyed by column name.
30
+
31
+ ---
32
+
33
+ ### KeySqlCursor
34
+
35
+ ```ts
36
+ type KeySqlCursor = Readonly<{
37
+ toArray: () => readonly KeySqlRow[];
38
+ }>;
39
+ ```
40
+
41
+ Materialized result of one executed statement.
42
+
43
+ ---
44
+
45
+ ### KeySql
46
+
47
+ ```ts
48
+ type KeySql = Readonly<{
49
+ exec: (statement, ...bindings) => KeySqlCursor;
50
+ }>;
51
+ ```
52
+
53
+ Synchronous SQL execution the key store runs its statements against. This shape
54
+ fits Cloudflare Durable Object SQLite (`state.storage.sql`) as is. A
55
+ `node:sqlite` adapter for hosts outside a Durable Object lives at
56
+ `@fungi.computer/ear-tag/keys/node`, kept out of this module so a Worker
57
+ consumer of this type never needs Node's own types to typecheck.
58
+
59
+ ---
60
+
61
+ ### RateLimitPolicy
62
+
63
+ ```ts
64
+ type RateLimitPolicy = Readonly<{
65
+ limit: number;
66
+ windowSeconds: number;
67
+ }>;
68
+ ```
69
+
70
+ A per-key fixed-window request policy.
71
+
72
+ ---
73
+
74
+ ### KeyRecord
75
+
76
+ ```ts
77
+ type KeyRecord<Capability> = Readonly<{
78
+ keyId: string;
79
+ owner: string;
80
+ name: string;
81
+ scope: Scope<Capability> | null;
82
+ grantVersion: number;
83
+ expiresAt: number | null;
84
+ revokedAt: number | null;
85
+ rateLimit: RateLimitPolicy | null;
86
+ lastUsedAt: number | null;
87
+ createdAt: number;
88
+ updatedAt: number;
89
+ }>;
90
+ ```
91
+
92
+ A stored key's durable state, without its bearer secret.
93
+
94
+ #### Type Parameters
95
+
96
+ | Type Parameter |
97
+ | ------------------------------- |
98
+ | `Capability` _extends_ `string` |
99
+
100
+ ---
101
+
102
+ ### KeyPrincipal
103
+
104
+ ```ts
105
+ type KeyPrincipal<Capability> = Readonly<{
106
+ keyId: string;
107
+ owner: string;
108
+ name: string;
109
+ scope: Scope<Capability>;
110
+ grantVersion: number;
111
+ expiresAt: number | null;
112
+ }>;
113
+ ```
114
+
115
+ A verified bearer credential: a live key's identity and current authority.
116
+
117
+ #### Type Parameters
118
+
119
+ | Type Parameter |
120
+ | ------------------------------- |
121
+ | `Capability` _extends_ `string` |
122
+
123
+ ---
124
+
125
+ ### KeyRefusalCode
126
+
127
+ ```ts
128
+ type KeyRefusalCode =
129
+ | "invalid"
130
+ | "denied"
131
+ | "conflict"
132
+ | "expired"
133
+ | "rate_limited"
134
+ | "unavailable";
135
+ ```
136
+
137
+ Stable, closed reasons a key-store operation refuses to proceed.
138
+
139
+ ---
140
+
141
+ ### KeyRefusal
142
+
143
+ ```ts
144
+ type KeyRefusal = Readonly<{
145
+ code: KeyRefusalCode;
146
+ retryAfterSeconds?: number;
147
+ }>;
148
+ ```
149
+
150
+ One closed refusal, carried as data rather than a thrown error type.
151
+
152
+ `invalid` means the caller's own input failed the operation's schema; it is the
153
+ caller's bug. `denied` means well-formed input was refused on its merits (no
154
+ authority, revoked, suspended). `unavailable` means the store could not read
155
+ back its own state (a corrupt row, a corrupt rate limit, or any other failure
156
+ that is not one of the other closed reasons); that is the store's own fault,
157
+ never the caller's, and every such failure is also logged before this outcome is
158
+ returned.
159
+
160
+ ---
161
+
162
+ ### KeyOutcome
163
+
164
+ ```ts
165
+ type KeyOutcome<Value> = Readonly<
166
+ | Readonly<{
167
+ kind: "ok";
168
+ value: Value;
169
+ }>
170
+ | Readonly<{
171
+ kind: "error";
172
+ error: KeyRefusal;
173
+ }>
174
+ >;
175
+ ```
176
+
177
+ The outcome of one key-store operation: its value, or a closed refusal.
178
+
179
+ #### Type Parameters
180
+
181
+ | Type Parameter |
182
+ | -------------- |
183
+ | `Value` |
184
+
185
+ ---
186
+
187
+ ### IssuerAuthority
188
+
189
+ ```ts
190
+ type IssuerAuthority<Capability> =
191
+ | Readonly<{
192
+ kind: "unrestricted";
193
+ }>
194
+ | Readonly<{
195
+ kind: "bounded";
196
+ grants: readonly Grant<Capability>[];
197
+ }>;
198
+ ```
199
+
200
+ What an issuing actor may grant. `"unrestricted"` may grant any capability in
201
+ the host's vocabulary; `"bounded"` may grant only a subset of its own live
202
+ grants, checked with the vocabulary's `isSubset`.
203
+
204
+ #### Type Parameters
205
+
206
+ | Type Parameter |
207
+ | ------------------------------- |
208
+ | `Capability` _extends_ `string` |
209
+
210
+ ---
211
+
212
+ ### AuthorityFence
213
+
214
+ ```ts
215
+ type AuthorityFence = Readonly<{
216
+ requestId: string;
217
+ keyId: string;
218
+ grantVersion: number;
219
+ expiresAt: number | null;
220
+ }>;
221
+ ```
222
+
223
+ One durable notice that a key's authority changed, for a host's own downstream
224
+ fencing.
225
+
226
+ ---
227
+
228
+ ### CreateKeyStoreOptions
229
+
230
+ ```ts
231
+ type CreateKeyStoreOptions<Capability> = Readonly<{
232
+ sql: KeySql;
233
+ commit: <Value>(body) => Promise<Value>;
234
+ vocabulary: GrantVocabulary<Capability>;
235
+ prefix: string;
236
+ authorizeIssuer: (actorId) => Promise<IssuerAuthority<Capability> | null>;
237
+ onAuthorityChange?: (fence) => void;
238
+ now?: () => number;
239
+ }>;
240
+ ```
241
+
242
+ Construction options for [createKeyStore](#createkeystore).
243
+
244
+ #### Type Parameters
245
+
246
+ | Type Parameter |
247
+ | ------------------------------- |
248
+ | `Capability` _extends_ `string` |
249
+
250
+ ---
251
+
252
+ ### IssueKeyInput
253
+
254
+ ```ts
255
+ type IssueKeyInput<Capability> = Readonly<{
256
+ name: string;
257
+ grants: readonly Grant<Capability>[];
258
+ keyId?: string;
259
+ expiresAt?: number;
260
+ rateLimit?: RateLimitPolicy;
261
+ }>;
262
+ ```
263
+
264
+ Input to [KeyStore](#keystore)'s `issue`.
265
+
266
+ #### Type Parameters
267
+
268
+ | Type Parameter |
269
+ | ------------------------------- |
270
+ | `Capability` _extends_ `string` |
271
+
272
+ ---
273
+
274
+ ### IssuedKey
275
+
276
+ ```ts
277
+ type IssuedKey<Capability> = Readonly<{
278
+ key: string;
279
+ record: KeyRecord<Capability>;
280
+ }>;
281
+ ```
282
+
283
+ Result of [KeyStore](#keystore)'s `issue`: the bearer secret and its durable
284
+ record.
285
+
286
+ #### Type Parameters
287
+
288
+ | Type Parameter |
289
+ | ------------------------------- |
290
+ | `Capability` _extends_ `string` |
291
+
292
+ ---
293
+
294
+ ### UpdateGrantsInput
295
+
296
+ ```ts
297
+ type UpdateGrantsInput<Capability> = Readonly<{
298
+ requestId: string;
299
+ keyId: string;
300
+ expectedGrantVersion: number;
301
+ grants: readonly Grant<Capability>[];
302
+ }>;
303
+ ```
304
+
305
+ Input to [KeyStore](#keystore)'s `updateGrants`: a compare-and-swap grant
306
+ replacement.
307
+
308
+ #### Type Parameters
309
+
310
+ | Type Parameter |
311
+ | ------------------------------- |
312
+ | `Capability` _extends_ `string` |
313
+
314
+ ---
315
+
316
+ ### RevokeInput
317
+
318
+ ```ts
319
+ type RevokeInput = Readonly<{
320
+ requestId: string;
321
+ keyId: string;
322
+ }>;
323
+ ```
324
+
325
+ Input to [KeyStore](#keystore)'s `revoke`: an exact, replayable revocation.
326
+
327
+ ---
328
+
329
+ ### AdmitUseInput
330
+
331
+ ```ts
332
+ type AdmitUseInput<Capability> = Readonly<{
333
+ capability: Capability;
334
+ target?: string;
335
+ requestId: string;
336
+ }>;
337
+ ```
338
+
339
+ Input to [KeyStore](#keystore)'s `admitUse`: one exact, replayable spend
340
+ admission.
341
+
342
+ #### Type Parameters
343
+
344
+ | Type Parameter |
345
+ | ------------------------------- |
346
+ | `Capability` _extends_ `string` |
347
+
348
+ ---
349
+
350
+ ### KeyStore
351
+
352
+ ```ts
353
+ type KeyStore<Capability> = Readonly<{
354
+ issue: (actorId, input) => Promise<KeyOutcome<IssuedKey<Capability>>>;
355
+ verify: (secret) => Promise<KeyOutcome<KeyPrincipal<Capability>>>;
356
+ current: (principal) => Promise<KeyOutcome<KeyPrincipal<Capability>>>;
357
+ list: (
358
+ actorId,
359
+ owner?,
360
+ ) => Promise<KeyOutcome<readonly KeyRecord<Capability>[]>>;
361
+ read: (actorId, keyId) => Promise<KeyOutcome<KeyPrincipal<Capability>>>;
362
+ updateGrants: (actorId, input) => Promise<KeyOutcome<KeyRecord<Capability>>>;
363
+ revoke: (actorId, input) => Promise<KeyOutcome<KeyRecord<Capability>>>;
364
+ suspendOwner: (owner, requestId) => Promise<KeyOutcome<void>>;
365
+ revokeAll: (closedAt) => Promise<KeyOutcome<void>>;
366
+ admitUse: (principal, input) => Promise<KeyOutcome<KeyPrincipal<Capability>>>;
367
+ touch: (keyId) => Promise<KeyOutcome<void>>;
368
+ }>;
369
+ ```
370
+
371
+ The operations one key store exposes over its tenant's keys.
372
+
373
+ #### Type Parameters
374
+
375
+ | Type Parameter |
376
+ | ------------------------------- |
377
+ | `Capability` _extends_ `string` |
378
+
379
+ ## Functions
380
+
381
+ ### createKeyStore()
382
+
383
+ ```ts
384
+ function createKeyStore<Capability>(options): KeyStore<Capability>;
385
+ ```
386
+
387
+ Create one tenant-scoped key store: bearer-key issuance, verification and
388
+ lifecycle over one host's capability vocabulary. One store instance is one
389
+ tenant; namespacing between tenants is the host's own table or storage boundary,
390
+ not a column inside this store.
391
+
392
+ #### Type Parameters
393
+
394
+ | Type Parameter |
395
+ | ------------------------------- |
396
+ | `Capability` _extends_ `string` |
397
+
398
+ #### Parameters
399
+
400
+ | Parameter | Type |
401
+ | --------- | ----------------------------------------------------------------- |
402
+ | `options` | [`CreateKeyStoreOptions`](#createkeystoreoptions)\<`Capability`\> |
403
+
404
+ #### Returns
405
+
406
+ [`KeyStore`](#keystore)\<`Capability`\>