@tinycloud/sdk-services 3.7.0-beta.3 → 3.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/dist/encryption/index.d.cts +4 -327
- package/dist/encryption/index.d.ts +4 -327
- package/dist/encryption/named-keys.cjs +1077 -0
- package/dist/encryption/named-keys.cjs.map +1 -0
- package/dist/encryption/named-keys.d.cts +220 -0
- package/dist/encryption/named-keys.d.ts +220 -0
- package/dist/encryption/named-keys.js +1041 -0
- package/dist/encryption/named-keys.js.map +1 -0
- package/dist/encryption/resource.cjs +293 -0
- package/dist/encryption/resource.cjs.map +1 -0
- package/dist/encryption/resource.d.cts +89 -0
- package/dist/encryption/resource.d.ts +89 -0
- package/dist/encryption/resource.js +257 -0
- package/dist/encryption/resource.js.map +1 -0
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/types-BGRzS1ob.d.ts +328 -0
- package/dist/types-B_rbS4XE.d.cts +328 -0
- package/package.json +27 -1
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { E as EncryptionCrypto, I as InlineEncryptedEnvelope, J as Json } from '../types-BGRzS1ob.js';
|
|
2
|
+
import { ParsedKeyResource } from './resource.js';
|
|
3
|
+
import '../types-DAOyIbXu.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Named-key client: key admin, descriptor reads, `ensureKey` and key-scoped
|
|
7
|
+
* encrypt / decrypt.
|
|
8
|
+
*
|
|
9
|
+
* Rules enforced here:
|
|
10
|
+
* - Everything is dark unless the node's `/info` `features` contains
|
|
11
|
+
* `encryption-named-keys-v1`. Without it no key ability, key URN or `keyPath`
|
|
12
|
+
* is sent to the node; the call throws `NAMED_KEYS_UNSUPPORTED` first.
|
|
13
|
+
* - Every invocation carries exactly ONE capability whose `with` is the EXACT
|
|
14
|
+
* key URN (a parsed `kind: "key"`; a prefix or bare network is never a
|
|
15
|
+
* target) and whose `can` is the one ability the call needs.
|
|
16
|
+
* - Admin bodies are hashed and serialized with the same canonical JSON used
|
|
17
|
+
* by the network-admin invocation (`canonicalHashHex` / `canonicalize`).
|
|
18
|
+
* - Envelope v2 carries `keyPath` and is wrapped to the KEY's public key. It is
|
|
19
|
+
* decrypted only through `POST /invoke` with a single decrypt capability on
|
|
20
|
+
* that key. v1 envelopes (no `keyPath`) go to the root-key path unchanged.
|
|
21
|
+
* A key and the root, or two keys, are never mixed in one invocation.
|
|
22
|
+
* - `key.delete` is not offered. The create body carries `deletable`, which is
|
|
23
|
+
* `true` exactly when the path starts with `apps/`; the node refuses it with
|
|
24
|
+
* `deletable_unavailable` while app-key deletion is not enabled there.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
declare const KEY_ADMIN_FACT_TYPE: "tinycloud.encryption.key-admin/v1";
|
|
28
|
+
declare const KEY_DESCRIBE_FACT_TYPE: "tinycloud.encryption.key-describe/v1";
|
|
29
|
+
declare const NAMED_KEY_ENVELOPE_VERSION: 2;
|
|
30
|
+
type NamedKeyErrorCode = "NAMED_KEYS_UNSUPPORTED" | "INVALID_KEY_TARGET" | "INVALID_ENVELOPE" | "INVALID_RESPONSE" | "KEY_BLOCKED" | "KEY_NOT_FOUND" | "KEY_EXISTS" | "NETWORK_NOT_FOUND" | "NETWORK_NOT_ACTIVE" | "KEY_LIMIT_EXCEEDED" | "DELETABLE_UNAVAILABLE"
|
|
31
|
+
/** The key is not deletable (a deterministic key answers 409 `key_not_deletable`). */
|
|
32
|
+
| "KEY_NOT_DELETABLE" | "KEY_PATH_INVALID" | "KEY_UNWRAP_FAILED"
|
|
33
|
+
/** Key is in a state other than active/blocked; `rawState` holds the node's string. */
|
|
34
|
+
| "KEY_UNAVAILABLE"
|
|
35
|
+
/** `ensureKey` found a key that is not deterministic. */
|
|
36
|
+
| "KEY_KIND_MISMATCH" | "DECRYPT_FAILED" | "NODE_ERROR"
|
|
37
|
+
/** The node rejected `receiverPublicKey` (400, invocation not consumed). */
|
|
38
|
+
| "RECEIVER_KEY_INVALID"
|
|
39
|
+
/** The node object lacks an invocation hook the node-sdk wiring needs. */
|
|
40
|
+
| "NODE_HOOK_MISSING";
|
|
41
|
+
/**
|
|
42
|
+
* Render an untrusted value (resource, path, node-supplied state, parser or
|
|
43
|
+
* signer text) for an error message: capped at 120 characters, then every
|
|
44
|
+
* character outside printable ASCII escaped, so bidi, zero-width and other
|
|
45
|
+
* format or control characters can never reach a terminal or log through a
|
|
46
|
+
* message. Raw values live only in non-message fields (`input`, `rawState`,
|
|
47
|
+
* `kind`, `detail`, `cause`).
|
|
48
|
+
*/
|
|
49
|
+
declare function safeEcho(value: unknown): string;
|
|
50
|
+
interface NamedKeyErrorInit {
|
|
51
|
+
status?: number;
|
|
52
|
+
/** The node's `<code>` prefix, when it sent one. */
|
|
53
|
+
nodeCode?: string;
|
|
54
|
+
/** The node's `<detail>` text. Raw: never in `message`. */
|
|
55
|
+
detail?: string;
|
|
56
|
+
/** Raw state string (KEY_UNAVAILABLE). Raw: never in `message`. */
|
|
57
|
+
rawState?: string;
|
|
58
|
+
kind?: string;
|
|
59
|
+
/** The rejected caller input (resource or path), unescaped. Raw: never in `message`. */
|
|
60
|
+
input?: string;
|
|
61
|
+
cause?: unknown;
|
|
62
|
+
}
|
|
63
|
+
declare class NamedKeyError extends Error {
|
|
64
|
+
readonly code: NamedKeyErrorCode;
|
|
65
|
+
readonly status?: number;
|
|
66
|
+
readonly nodeCode?: string;
|
|
67
|
+
readonly detail?: string;
|
|
68
|
+
readonly rawState?: string;
|
|
69
|
+
readonly kind?: string;
|
|
70
|
+
readonly input?: string;
|
|
71
|
+
constructor(code: NamedKeyErrorCode, message: string, init?: NamedKeyErrorInit);
|
|
72
|
+
}
|
|
73
|
+
/** Map a node plain-text `<code>: <detail>` error response to a typed error. */
|
|
74
|
+
declare function mapNodeKeyError(status: number, text: string, context: string): NamedKeyError;
|
|
75
|
+
interface PublicKeyDescriptor {
|
|
76
|
+
networkId: string;
|
|
77
|
+
keyPath: string;
|
|
78
|
+
alg: string;
|
|
79
|
+
keyVersion: number;
|
|
80
|
+
publicEncryptionKey: string;
|
|
81
|
+
}
|
|
82
|
+
interface KeyDescriptor extends PublicKeyDescriptor {
|
|
83
|
+
/** Raw node state string (`active`, `blocked`, ...). */
|
|
84
|
+
state: string;
|
|
85
|
+
/** `deterministic` outside `apps/`, `deletable` under it; kept as a string so unknown kinds surface. */
|
|
86
|
+
kind: string;
|
|
87
|
+
createdAt?: string;
|
|
88
|
+
updatedAt?: string;
|
|
89
|
+
}
|
|
90
|
+
/** v2 inline envelope: v1 fields plus `keyPath`, wrapped to the key's public key. */
|
|
91
|
+
interface NamedKeyEnvelope extends Omit<InlineEncryptedEnvelope, "v"> {
|
|
92
|
+
v: typeof NAMED_KEY_ENVELOPE_VERSION;
|
|
93
|
+
keyPath: string;
|
|
94
|
+
}
|
|
95
|
+
interface NamedKeyInvocationInput {
|
|
96
|
+
targetNode: string;
|
|
97
|
+
/** The EXACT key URN. This is the single capability's `with`. */
|
|
98
|
+
resource: string;
|
|
99
|
+
/** The single capability's `can`. */
|
|
100
|
+
action: string;
|
|
101
|
+
facts: Record<string, unknown>;
|
|
102
|
+
}
|
|
103
|
+
interface NamedKeyClientConfig {
|
|
104
|
+
host: string;
|
|
105
|
+
crypto: EncryptionCrypto;
|
|
106
|
+
fetch: typeof fetch;
|
|
107
|
+
/** Network used when a call does not name one. */
|
|
108
|
+
defaultNetworkId: () => string;
|
|
109
|
+
/** Mint one single-capability invocation and return the Authorization header value. */
|
|
110
|
+
signInvocation: (input: NamedKeyInvocationInput) => Promise<{
|
|
111
|
+
authorization: string;
|
|
112
|
+
invocationCid: string;
|
|
113
|
+
}>;
|
|
114
|
+
/**
|
|
115
|
+
* Decrypt a v1 (root key, bare network capability) envelope exactly as the
|
|
116
|
+
* existing network decrypt path does.
|
|
117
|
+
*/
|
|
118
|
+
decryptRoot?: (envelope: InlineEncryptedEnvelope) => Promise<{
|
|
119
|
+
ok: true;
|
|
120
|
+
data: Uint8Array;
|
|
121
|
+
} | {
|
|
122
|
+
ok: false;
|
|
123
|
+
error: {
|
|
124
|
+
message: string;
|
|
125
|
+
};
|
|
126
|
+
}>;
|
|
127
|
+
}
|
|
128
|
+
interface KeyCallOptions {
|
|
129
|
+
/** Full network id URN. Defaults to the client's default network. */
|
|
130
|
+
networkId?: string;
|
|
131
|
+
}
|
|
132
|
+
interface KeyEncryptOptions extends KeyCallOptions {
|
|
133
|
+
aad?: Uint8Array;
|
|
134
|
+
metadata?: Record<string, string>;
|
|
135
|
+
}
|
|
136
|
+
type DecryptManyResult = {
|
|
137
|
+
ok: true;
|
|
138
|
+
data: Uint8Array;
|
|
139
|
+
} | {
|
|
140
|
+
ok: false;
|
|
141
|
+
error: NamedKeyError;
|
|
142
|
+
};
|
|
143
|
+
/** Accept only a parsed `kind: "key"`; a prefix or bare network is never a target. */
|
|
144
|
+
declare function requireKeyTarget(resource: string): ParsedKeyResource;
|
|
145
|
+
/** `{type, targetNode, networkId, keyPath, action, bodyHash}` for key admin routes. */
|
|
146
|
+
declare function buildKeyAdminFacts(input: {
|
|
147
|
+
crypto: EncryptionCrypto;
|
|
148
|
+
targetNode: string;
|
|
149
|
+
keyResource: string;
|
|
150
|
+
action: string;
|
|
151
|
+
body: Json;
|
|
152
|
+
}): Record<string, unknown>;
|
|
153
|
+
/** `{type, targetNode, networkId, keyPath}`; no body hash. */
|
|
154
|
+
declare function buildKeyDescribeFacts(input: {
|
|
155
|
+
targetNode: string;
|
|
156
|
+
keyResource: string;
|
|
157
|
+
}): Record<string, unknown>;
|
|
158
|
+
declare class NamedKeyClient {
|
|
159
|
+
private readonly config;
|
|
160
|
+
/** One `/info` read per client: the node DID once the feature is confirmed. */
|
|
161
|
+
private nodeId?;
|
|
162
|
+
constructor(config: NamedKeyClientConfig);
|
|
163
|
+
private networkFor;
|
|
164
|
+
private keyUrn;
|
|
165
|
+
/**
|
|
166
|
+
* Require the named-keys feature and return the node DID. The first call
|
|
167
|
+
* reads `/info`; a positive answer is cached for the life of this client, so
|
|
168
|
+
* later calls make no `/info` request. A node without the feature is NOT
|
|
169
|
+
* cached: the typed `NAMED_KEYS_UNSUPPORTED` error is thrown and the next
|
|
170
|
+
* call re-reads (so a retry sees an upgraded node). No key request is made
|
|
171
|
+
* before the gate passes.
|
|
172
|
+
*/
|
|
173
|
+
private requireNode;
|
|
174
|
+
/** Clear the cached `/info` answer; the next call reads it again. */
|
|
175
|
+
refreshNodeInfo(): void;
|
|
176
|
+
private readNodeInfo;
|
|
177
|
+
private keysUrl;
|
|
178
|
+
/** Public GET: the key's public key. Derive-only (no 404) outside `apps/`; under `apps/` the node answers 404. */
|
|
179
|
+
getPublicKey(path: string, options?: KeyCallOptions): Promise<PublicKeyDescriptor>;
|
|
180
|
+
/**
|
|
181
|
+
* Authenticated GET: the full descriptor, or `null` on `key_not_found`.
|
|
182
|
+
* `ability` is the one capability the invocation carries (default decrypt).
|
|
183
|
+
*/
|
|
184
|
+
describeKey(path: string, options?: KeyCallOptions & {
|
|
185
|
+
ability?: string;
|
|
186
|
+
}): Promise<KeyDescriptor | null>;
|
|
187
|
+
/** Public fields of an authenticated describe (decrypt ability); `key_not_found` throws. */
|
|
188
|
+
private describePublic;
|
|
189
|
+
/** The authenticated GET response body, or `null` on `key_not_found`. */
|
|
190
|
+
private describeBody;
|
|
191
|
+
private admin;
|
|
192
|
+
/** `key.create`: `deletable` is `true` exactly under `apps/`, else a deterministic key. */
|
|
193
|
+
createKey(path: string, options?: KeyCallOptions): Promise<KeyDescriptor>;
|
|
194
|
+
blockKey(path: string, options?: KeyCallOptions): Promise<KeyDescriptor>;
|
|
195
|
+
unblockKey(path: string, options?: KeyCallOptions): Promise<KeyDescriptor>;
|
|
196
|
+
/**
|
|
197
|
+
* Make sure a key exists and is usable: authenticated GET; on
|
|
198
|
+
* `key_not_found` create it; on 409 `key_exists` read it again. Succeeds only
|
|
199
|
+
* for `state: "active"` and the kind the path implies: `deletable` under
|
|
200
|
+
* `apps/`, `deterministic` elsewhere.
|
|
201
|
+
*/
|
|
202
|
+
ensureKey(path: string, options?: KeyCallOptions): Promise<KeyDescriptor>;
|
|
203
|
+
/** Encrypt to a named key: envelope v2, symmetric key wrapped to the key's public key. */
|
|
204
|
+
encrypt(path: string, plaintext: Uint8Array, options?: KeyEncryptOptions): Promise<NamedKeyEnvelope>;
|
|
205
|
+
/**
|
|
206
|
+
* Decrypt one envelope. v1 (no `keyPath`) uses the root-key path exactly as
|
|
207
|
+
* before; v2 uses one decrypt capability on the exact key via `/invoke`.
|
|
208
|
+
*/
|
|
209
|
+
decrypt(envelope: InlineEncryptedEnvelope | NamedKeyEnvelope): Promise<Uint8Array>;
|
|
210
|
+
/**
|
|
211
|
+
* Decrypt a batch. Each envelope is its own invocation with its own single
|
|
212
|
+
* capability, so v1 and v2 (or two different keys) are never combined.
|
|
213
|
+
*/
|
|
214
|
+
decryptMany(envelopes: ReadonlyArray<InlineEncryptedEnvelope | NamedKeyEnvelope>): Promise<DecryptManyResult[]>;
|
|
215
|
+
private decryptRoot;
|
|
216
|
+
private validateKeyEnvelope;
|
|
217
|
+
private decryptKey;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export { type DecryptManyResult, KEY_ADMIN_FACT_TYPE, KEY_DESCRIBE_FACT_TYPE, type KeyCallOptions, type KeyDescriptor, type KeyEncryptOptions, NAMED_KEY_ENVELOPE_VERSION, NamedKeyClient, type NamedKeyClientConfig, type NamedKeyEnvelope, NamedKeyError, type NamedKeyErrorCode, type NamedKeyErrorInit, type NamedKeyInvocationInput, type PublicKeyDescriptor, buildKeyAdminFacts, buildKeyDescribeFacts, mapNodeKeyError, requireKeyTarget, safeEcho };
|