@k9o/kibo 0.0.0-stage → 1.1.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.
@@ -0,0 +1,266 @@
1
+ import { HttpClientConfig } from '@k9o/core/http';
2
+ import { Envelope } from '@k9o/core/envelope';
3
+ import { StoreZkDekInput, ZkDekHandle, ZkDekRecord, ListSecretsInput, ListSecretsResult, SecretSummary, CreateSecretInput, RevealChallenge, RevealSecretResult, UpdateSecretInput, UpdateSecretResult, RotateSecretResult, MoveSecretResult, KmsProvider } from './types.js';
4
+ export { AttestationTier, SecretVisibility } from './types.js';
5
+
6
+ /**
7
+ * `client.kibo.vault.*` — the Kibo vault surface.
8
+ *
9
+ * `vault.zkDeks.{store,fetch}` — member-plane,
10
+ * project-scoped storage of the opaque customer-wrapped DEK envelope. Zero
11
+ * crypto SDK-side: this is a plain authenticated REST round-trip carrying an
12
+ * opaque blob (the wrapping happens in the ZK core, piece C). The encryption
13
+ * surface (`kibo.encrypt`/`decrypt`) is provided by the ZK core binding when it is
14
+ * bundled.
15
+ */
16
+
17
+ declare function makeVaultNamespace(config: HttpClientConfig): {
18
+ /** ZK-DEK opaque store/fetch (F.5). */
19
+ zkDeks: {
20
+ /**
21
+ * Store an opaque customer-wrapped DEK envelope.
22
+ * `POST /@<projectSlug>/vault/zk-deks` → the `zkdek_<base62>` handle.
23
+ * The SDK ships the envelope verbatim; it is never parsed here.
24
+ */
25
+ store(input: StoreZkDekInput): Promise<Envelope<ZkDekHandle>>;
26
+ /**
27
+ * Fetch a stored `WrappedDek` by its handle.
28
+ * `GET /@<projectSlug>/vault/zk-deks/<id>` → the opaque envelope + the
29
+ * non-secret `provider`/`keyVersionRef` the caller needs to unwrap it.
30
+ */
31
+ fetch(id: string): Promise<Envelope<ZkDekRecord>>;
32
+ };
33
+ /**
34
+ * typed secrets surface (`services/gateway/src/routes/vault-secrets.ts`) — the full family:
35
+ * list/get/create/revealChallenge/reveal/update/rotate/move/delete. Every operation on a NAMED
36
+ * secret (everything except `list`) requires `region` — live-verified against staging, not
37
+ * documented in the route's OpenAPI schema. `list` is the one exception (verified it does NOT
38
+ * need `region`).
39
+ *
40
+ * Response shapes for `update`/`rotate`/`move` are typed to what the gateway ACTUALLY returns
41
+ * (live-verified), not the OpenAPI's documented (and inaccurate for these three) `SecretSummary` —
42
+ * see the 🔴 notes on `UpdateSecretResult`/`RotateSecretResult`/`MoveSecretResult` in `types.ts`.
43
+ */
44
+ secrets: {
45
+ /** List secrets (metadata only — never lists ciphertext). `GET /@<projectSlug>/vault/secrets`.
46
+ * The one secrets operation that does NOT need `region` (live-verified). */
47
+ list(input?: ListSecretsInput): Promise<Envelope<ListSecretsResult>>;
48
+ /**
49
+ * Read a secret's metadata (never its value — use `revealChallenge`+`reveal` for that).
50
+ * `GET /@<projectSlug>/vault/secrets/<name>?region=<region>`.
51
+ *
52
+ * 🔴 KNOWN LIVE BUG (staging, 2026-09-05): this call currently fails with
53
+ * `K9O_REVEAL_CHALLENGE_REQUIRED` on every attempt — the gateway/kibo does not honor the
54
+ * documented "no `X-K9O-Reveal-Challenge` header ⇒ return metadata" behavior; it demands a
55
+ * challenge unconditionally. Implemented per the documented contract (this is a backend defect,
56
+ * not a client workaround); `list({prefix: exactName})` is the current working alternative for a
57
+ * single secret's metadata until the gateway/kibo side is fixed.
58
+ */
59
+ get(name: string, opts: {
60
+ region: string;
61
+ }): Promise<Envelope<SecretSummary>>;
62
+ /**
63
+ * Create a secret under the caller's own auth.
64
+ * `POST /@<projectSlug>/vault/secrets/<name>?region=<region>` → the `sec_<base62>` summary.
65
+ *
66
+ * 🔴 `region` is REQUIRED on the query string, live-verified against staging — the vault-forward
67
+ * proxy fail-closes with `K9O_INVALID_FIELD_VALUE` ("this request requires an authoritative
68
+ * region") without it. Distinct from any `region` carried inside `input.value`'s envelope (e.g.
69
+ * the BYOS aws_sigv4 STS-signing region): this one scopes the vault WRITE itself, mirroring the
70
+ * gateway's `gatewayRegion()` residency guard (region-guard.ts) that closed a 2026-08 wrong-region
71
+ * incident for the audit path — the request-shape unit tests never caught this because they don't
72
+ * exercise a real gateway.
73
+ */
74
+ create(input: CreateSecretInput): Promise<Envelope<SecretSummary>>;
75
+ /** Mint a single-use reveal challenge — present it as `X-K9O-Reveal-Challenge` on the
76
+ * immediately-following `reveal()` call. `POST .../<name>?op=reveal-challenge&region=<region>`. */
77
+ revealChallenge(name: string, opts: {
78
+ region: string;
79
+ }): Promise<Envelope<RevealChallenge>>;
80
+ /** Reveal a secret's plaintext value using a single-use challenge from `revealChallenge()`.
81
+ * `GET .../<name>?region=<region>` with `X-K9O-Reveal-Challenge`. Decodes the wire's base64
82
+ * `value` back to plaintext (live-verified: the reveal response's `value` is base64, symmetric
83
+ * with `create`'s encode). */
84
+ reveal(name: string, opts: {
85
+ region: string;
86
+ challenge: string;
87
+ }): Promise<Envelope<RevealSecretResult>>;
88
+ /** Update a secret's value (bumps version) — owner-only. `PUT .../<name>?region=<region>`.
89
+ * 🔴 Returns only `{id, name, version}` live (see `UpdateSecretResult`), not the full summary
90
+ * the OpenAPI schema documents — call `get()` after if you need the rest. */
91
+ update(name: string, input: UpdateSecretInput): Promise<Envelope<UpdateSecretResult>>;
92
+ /** Rotate a secret's wrapping key (re-wraps under a fresh `kid`; content unchanged) — owner-only.
93
+ * `POST .../<name>?op=rotate&region=<region>`. */
94
+ rotate(name: string, opts: {
95
+ region: string;
96
+ }): Promise<Envelope<RotateSecretResult>>;
97
+ /** Move (rename) a secret's hierarchical path — owner-only.
98
+ * `POST .../<name>?op=move&region=<region>`. */
99
+ move(name: string, opts: {
100
+ region: string;
101
+ newPath: string;
102
+ }): Promise<Envelope<MoveSecretResult>>;
103
+ /** Retire a secret — owner-only. `DELETE .../<name>?region=<region>` → `204 No Content`. */
104
+ delete(name: string, opts: {
105
+ region: string;
106
+ }): Promise<Envelope<void>>;
107
+ };
108
+ };
109
+
110
+ /**
111
+ * `createKiboClient(config)` — per-instance Kibo (ZK vault) SDK factory.
112
+ *
113
+ * Composes into `@k9o/core` as `client.kibo` (re-export, available when a
114
+ * project is bound — the same composition pattern as `@k9o/gate`). Reuses the
115
+ * core HTTP layer (`@k9o/core/http`) so the bearer/header/retry contract is
116
+ * identical to the rest of the SDK pool.
117
+ */
118
+
119
+ /** Shape of the per-instance client returned by `createKiboClient`. */
120
+ type KiboClient = {
121
+ /** Vault surface — `client.kibo.vault.zkDeks.{store,fetch}` (F.5). */
122
+ vault: ReturnType<typeof makeVaultNamespace>;
123
+ };
124
+ /** Construct a Kibo client bound to the supplied (core) HTTP config. */
125
+ declare function createKiboClient(config: HttpClientConfig): KiboClient;
126
+
127
+ /**
128
+ * TS contract for the ZK encrypt/decrypt FFI surface — mirrors the Rust
129
+ * `kibo-kms-rest-ffi::types` (the bound core, piece C) field-for-field.
130
+ *
131
+ * These types cross the wasm boundary as plain JS objects (serde-wasm-bindgen),
132
+ * so the field names + enum wire-tokens must match the Rust serde exactly:
133
+ * - `KmsProvider` kebab-case (`aws-kms`, `gcp-kms`, `azure-kv`, `hashicorp-vault`)
134
+ * - all other enums snake_case (`byok`, `local_envelope`, `hardware_backed`, …)
135
+ * - bytes (`Vec<u8>`) `Uint8Array` at the boundary
136
+ *
137
+ * Strict-ZK invariant: the `secret` in `KiboCredential` is a customer-issued
138
+ * short-lived federated token — never a platform KEK; it is zeroized in the core
139
+ * after use and never logged or returned. The platform never sees plaintext.
140
+ */
141
+
142
+ /** Custody posture for an encrypt call. `platform-managed` is structurally absent
143
+ * here — `kibo-kms-rest` is the KEK-free customer-KMS layer (ZK is never PM). */
144
+ type KiboPosture = "byok" | "hyok";
145
+ /** Explicit strategy pin. Omit → `local_envelope` (the posture default). */
146
+ type KiboStrategy = "local_envelope" | "customer_kms_oracle";
147
+ /** Oracle routing mode. Omit → `brokered` (default). */
148
+ type KiboOracleMode = "brokered" | "direct";
149
+ /** Device attestation tier bound into the AAD for every operation. */
150
+ type KiboAttestationTier = "software" | "hardware_backed" | "confidential";
151
+ /** The min-custody-posture floor ladder (3-mode; `platform_managed` = no floor).
152
+ * Ordering: `PLATFORM_MANAGED < BYOK < HYOK`. */
153
+ type KiboMinPosture = "platform_managed" | "byok" | "hyok";
154
+ /** Acceptable oracle-mode set (the `allowed_oracle_modes` policy dial). */
155
+ interface KiboAllowedOracleModes {
156
+ brokered: boolean;
157
+ direct: boolean;
158
+ }
159
+ /** Project-declared crypto-posture floor. Omit fields for the
160
+ * most-permissive default (`platform_managed` floor + both oracle modes). */
161
+ interface KiboPosturePolicy {
162
+ min_custody_posture?: KiboMinPosture;
163
+ allowed_oracle_modes?: KiboAllowedOracleModes;
164
+ }
165
+ /** Short-lived customer KMS credential — the edge device's federated token.
166
+ * `secret` is treated as secret material (zeroized in-core; never returned). */
167
+ interface KiboCredential {
168
+ secret: string;
169
+ expires_at_unix_secs: number;
170
+ }
171
+ /** Key version reference identifying the customer KMS key. `external_ref` is
172
+ * provider-specific (AWS key ARN / GCP resource name / Azure key URL / Vault
173
+ * `<mount>/<key>:<ver>`). `version` is the monotone KEK-rotation counter. */
174
+ interface KiboKeyRef {
175
+ version: number;
176
+ external_ref: string;
177
+ }
178
+ /** Provider-specific init params. Only the compiled-in provider's field is read. */
179
+ interface KiboProviderConfig {
180
+ aws_region?: string;
181
+ vault_address?: string;
182
+ }
183
+ /** A single encryption-context key/value pair. Bound into the AAD at encrypt and
184
+ * re-supplied byte-for-byte at decrypt. (Record shape — uniffi can't cross
185
+ * tuples; the wasm JSON is `[{"key":"…","value":"…"}]`.) `kibo:` is reserved. */
186
+ interface KiboKvPair {
187
+ key: string;
188
+ value: string;
189
+ }
190
+ /** All inputs to `encrypt` — mirrors Rust `EncryptInput`. */
191
+ interface KiboEncryptInput {
192
+ provider: KmsProvider;
193
+ posture: KiboPosture;
194
+ strategy?: KiboStrategy;
195
+ oracle_mode?: KiboOracleMode;
196
+ kms_cred: KiboCredential;
197
+ key_ref: KiboKeyRef;
198
+ provider_config: KiboProviderConfig;
199
+ attestation_tier: KiboAttestationTier;
200
+ encryption_context: KiboKvPair[];
201
+ /** Plaintext bytes to encrypt. */
202
+ plaintext: Uint8Array;
203
+ posture_policy?: KiboPosturePolicy;
204
+ }
205
+ /** All inputs to `decrypt` — mirrors Rust `DecryptInput`. `strategy`,
206
+ * `attestation_tier`, and `encryption_context` MUST be re-supplied (never read
207
+ * from the envelope — anti-envelope-substitution discipline). */
208
+ interface KiboDecryptInput {
209
+ kms_cred: KiboCredential;
210
+ provider_config: KiboProviderConfig;
211
+ /** The canonical (`b"KIBO"`) envelope from a prior `encrypt`. */
212
+ envelope: Uint8Array;
213
+ strategy: KiboStrategy;
214
+ attestation_tier: KiboAttestationTier;
215
+ encryption_context: KiboKvPair[];
216
+ }
217
+ /** Output of `encrypt` — the opaque ZKFE envelope (pass straight to `decrypt`). */
218
+ interface KiboEncryptOutput {
219
+ envelope: Uint8Array;
220
+ }
221
+ /** Output of `decrypt` — the recovered plaintext. */
222
+ interface KiboDecryptOutput {
223
+ plaintext: Uint8Array;
224
+ }
225
+
226
+ /**
227
+ * ZK encrypt/decrypt — the thin TS wrapper over the bound crypto core
228
+ * (`kibo-kms-rest-ffi`, piece C) compiled to wasm. ZERO crypto here: every
229
+ * wrap/unwrap, envelope framing, posture-floor enforcement, and KMS round-trip
230
+ * lives in the audited Rust core. This layer only marshals the typed input
231
+ * across the wasm boundary and maps the core's error string → `KError`.
232
+ *
233
+ * The core exposes `zk_encrypt`/`zk_decrypt` (async) taking/returning plain JS
234
+ * objects via serde-wasm-bindgen, and rejecting with the `ZkFfiError` display
235
+ * string (`"<K9O_CODE>: <message>"`, optionally with a posture-violation tail).
236
+ *
237
+ * Composes into `@k9o/core` as `client.kibo.encrypt`/`decrypt`; the F.5
238
+ * `vault.zkDeks.{store,fetch}` surface (envelope persistence) is separate +
239
+ * decoupled (the core never sees the store).
240
+ */
241
+
242
+ /** The minimal surface the bound ZK-core wasm exposes. */
243
+ interface ZkWasm {
244
+ zk_encrypt(input: unknown): Promise<unknown>;
245
+ zk_decrypt(input: unknown): Promise<unknown>;
246
+ }
247
+ /**
248
+ * Inject a pre-loaded core wasm module. Hosts that bundle the wasm themselves
249
+ * (browser/RN, or a test) call this; otherwise `encrypt`/`decrypt` lazy-load
250
+ * the vendored per-provider artifact.
251
+ */
252
+ declare function setZkWasm(mod: ZkWasm): void;
253
+ /**
254
+ * Encrypt `input.plaintext` via the customer KMS, client-side. Returns the
255
+ * opaque ZKFE envelope — store it via `vault.zkDeks.store` (F.5) or keep it
256
+ * yourself; it is meaningless to the platform.
257
+ */
258
+ declare function encrypt(input: KiboEncryptInput): Promise<KiboEncryptOutput>;
259
+ /**
260
+ * Decrypt a ZKFE `input.envelope`. `strategy`, `attestation_tier`, and
261
+ * `encryption_context` MUST match the values used at encrypt — they are AAD-bound
262
+ * and never recovered from the envelope (anti-substitution discipline).
263
+ */
264
+ declare function decrypt(input: KiboDecryptInput): Promise<KiboDecryptOutput>;
265
+
266
+ export { CreateSecretInput, type KiboAllowedOracleModes, type KiboAttestationTier, type KiboClient, type KiboCredential, type KiboDecryptInput, type KiboDecryptOutput, type KiboEncryptInput, type KiboEncryptOutput, type KiboKeyRef, type KiboKvPair, type KiboMinPosture, type KiboOracleMode, type KiboPosture, type KiboPosturePolicy, type KiboProviderConfig, type KiboStrategy, KmsProvider, ListSecretsInput, ListSecretsResult, MoveSecretResult, RevealChallenge, RevealSecretResult, RotateSecretResult, SecretSummary, StoreZkDekInput, UpdateSecretInput, UpdateSecretResult, ZkDekHandle, ZkDekRecord, type ZkWasm, createKiboClient, decrypt, encrypt, makeVaultNamespace, setZkWasm };
package/dist/index.js ADDED
@@ -0,0 +1,259 @@
1
+ // src/client-factory.ts
2
+ import "@k9o/core/http";
3
+
4
+ // src/vault.ts
5
+ import { request } from "@k9o/core/http";
6
+ import { projectPath } from "@k9o/core/url-grammar";
7
+ import { KError } from "@k9o/core/errors";
8
+ function encodeBase64Utf8(plaintext) {
9
+ return btoa(unescape(encodeURIComponent(plaintext)));
10
+ }
11
+ function decodeBase64Utf8(b64) {
12
+ return decodeURIComponent(escape(atob(b64)));
13
+ }
14
+ function requireProjectSlug(config) {
15
+ if (config.projectSlug === void 0 || config.projectSlug.length === 0) {
16
+ throw new KError({
17
+ code: "K9O_MISSING_PROJECT_CONTEXT",
18
+ message: "client.kibo.vault requires a bound projectSlug (member-plane resource)",
19
+ context: {},
20
+ recommendation: "Pass projectSlug when constructing the client."
21
+ });
22
+ }
23
+ return config.projectSlug;
24
+ }
25
+ function makeVaultNamespace(config) {
26
+ return {
27
+ /** ZK-DEK opaque store/fetch (F.5). */
28
+ zkDeks: {
29
+ /**
30
+ * Store an opaque customer-wrapped DEK envelope.
31
+ * `POST /@<projectSlug>/vault/zk-deks` → the `zkdek_<base62>` handle.
32
+ * The SDK ships the envelope verbatim; it is never parsed here.
33
+ */
34
+ async store(input) {
35
+ return request(config, {
36
+ method: "POST",
37
+ path: projectPath(requireProjectSlug(config), "vault/zk-deks"),
38
+ body: input
39
+ });
40
+ },
41
+ /**
42
+ * Fetch a stored `WrappedDek` by its handle.
43
+ * `GET /@<projectSlug>/vault/zk-deks/<id>` → the opaque envelope + the
44
+ * non-secret `provider`/`keyVersionRef` the caller needs to unwrap it.
45
+ */
46
+ async fetch(id) {
47
+ return request(config, {
48
+ method: "GET",
49
+ path: projectPath(requireProjectSlug(config), `vault/zk-deks/${encodeURIComponent(id)}`)
50
+ });
51
+ }
52
+ },
53
+ /**
54
+ * typed secrets surface (`services/gateway/src/routes/vault-secrets.ts`) — the full family:
55
+ * list/get/create/revealChallenge/reveal/update/rotate/move/delete. Every operation on a NAMED
56
+ * secret (everything except `list`) requires `region` — live-verified against staging, not
57
+ * documented in the route's OpenAPI schema. `list` is the one exception (verified it does NOT
58
+ * need `region`).
59
+ *
60
+ * Response shapes for `update`/`rotate`/`move` are typed to what the gateway ACTUALLY returns
61
+ * (live-verified), not the OpenAPI's documented (and inaccurate for these three) `SecretSummary` —
62
+ * see the 🔴 notes on `UpdateSecretResult`/`RotateSecretResult`/`MoveSecretResult` in `types.ts`.
63
+ */
64
+ secrets: {
65
+ /** List secrets (metadata only — never lists ciphertext). `GET /@<projectSlug>/vault/secrets`.
66
+ * The one secrets operation that does NOT need `region` (live-verified). */
67
+ async list(input) {
68
+ return request(config, {
69
+ method: "GET",
70
+ path: projectPath(requireProjectSlug(config), "vault/secrets"),
71
+ query: { prefix: input?.prefix, cursor: input?.cursor, limit: input?.limit }
72
+ });
73
+ },
74
+ /**
75
+ * Read a secret's metadata (never its value — use `revealChallenge`+`reveal` for that).
76
+ * `GET /@<projectSlug>/vault/secrets/<name>?region=<region>`.
77
+ *
78
+ * 🔴 KNOWN LIVE BUG (staging, 2026-09-05): this call currently fails with
79
+ * `K9O_REVEAL_CHALLENGE_REQUIRED` on every attempt — the gateway/kibo does not honor the
80
+ * documented "no `X-K9O-Reveal-Challenge` header ⇒ return metadata" behavior; it demands a
81
+ * challenge unconditionally. Implemented per the documented contract (this is a backend defect,
82
+ * not a client workaround); `list({prefix: exactName})` is the current working alternative for a
83
+ * single secret's metadata until the gateway/kibo side is fixed.
84
+ */
85
+ async get(name, opts) {
86
+ return request(config, {
87
+ method: "GET",
88
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
89
+ query: { region: opts.region }
90
+ });
91
+ },
92
+ /**
93
+ * Create a secret under the caller's own auth.
94
+ * `POST /@<projectSlug>/vault/secrets/<name>?region=<region>` → the `sec_<base62>` summary.
95
+ *
96
+ * 🔴 `region` is REQUIRED on the query string, live-verified against staging — the vault-forward
97
+ * proxy fail-closes with `K9O_INVALID_FIELD_VALUE` ("this request requires an authoritative
98
+ * region") without it. Distinct from any `region` carried inside `input.value`'s envelope (e.g.
99
+ * the BYOS aws_sigv4 STS-signing region): this one scopes the vault WRITE itself, mirroring the
100
+ * gateway's `gatewayRegion()` residency guard (region-guard.ts) that closed a 2026-08 wrong-region
101
+ * incident for the audit path — the request-shape unit tests never caught this because they don't
102
+ * exercise a real gateway.
103
+ */
104
+ async create(input) {
105
+ const { name, region, value, ...rest } = input;
106
+ return request(config, {
107
+ method: "POST",
108
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
109
+ query: { region },
110
+ // Live-verified against staging: the wire `value` MUST be base64 — a raw plaintext string
111
+ // (matching the route's own "the plaintext to seal" OpenAPI description literally) is
112
+ // rejected with K9O_INVALID_FIELD_VALUE "Request body could not be parsed." `input.value`
113
+ // stays the caller-facing plaintext; base64 is purely a wire-transport detail handled here.
114
+ body: { ...rest, value: encodeBase64Utf8(value) }
115
+ });
116
+ },
117
+ /** Mint a single-use reveal challenge — present it as `X-K9O-Reveal-Challenge` on the
118
+ * immediately-following `reveal()` call. `POST .../<name>?op=reveal-challenge&region=<region>`. */
119
+ async revealChallenge(name, opts) {
120
+ return request(config, {
121
+ method: "POST",
122
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
123
+ query: { op: "reveal-challenge", region: opts.region }
124
+ });
125
+ },
126
+ /** Reveal a secret's plaintext value using a single-use challenge from `revealChallenge()`.
127
+ * `GET .../<name>?region=<region>` with `X-K9O-Reveal-Challenge`. Decodes the wire's base64
128
+ * `value` back to plaintext (live-verified: the reveal response's `value` is base64, symmetric
129
+ * with `create`'s encode). */
130
+ async reveal(name, opts) {
131
+ const envelope = await request(config, {
132
+ method: "GET",
133
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
134
+ query: { region: opts.region },
135
+ headers: { "X-K9O-Reveal-Challenge": opts.challenge }
136
+ });
137
+ return { ...envelope, data: { ...envelope.data, value: decodeBase64Utf8(envelope.data.value) } };
138
+ },
139
+ /** Update a secret's value (bumps version) — owner-only. `PUT .../<name>?region=<region>`.
140
+ * 🔴 Returns only `{id, name, version}` live (see `UpdateSecretResult`), not the full summary
141
+ * the OpenAPI schema documents — call `get()` after if you need the rest. */
142
+ async update(name, input) {
143
+ return request(config, {
144
+ method: "PUT",
145
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
146
+ query: { region: input.region },
147
+ body: { value: encodeBase64Utf8(input.value), ...input.metadata !== void 0 ? { metadata: input.metadata } : {} }
148
+ });
149
+ },
150
+ /** Rotate a secret's wrapping key (re-wraps under a fresh `kid`; content unchanged) — owner-only.
151
+ * `POST .../<name>?op=rotate&region=<region>`. */
152
+ async rotate(name, opts) {
153
+ return request(config, {
154
+ method: "POST",
155
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
156
+ query: { op: "rotate", region: opts.region }
157
+ });
158
+ },
159
+ /** Move (rename) a secret's hierarchical path — owner-only.
160
+ * `POST .../<name>?op=move&region=<region>`. */
161
+ async move(name, opts) {
162
+ return request(config, {
163
+ method: "POST",
164
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
165
+ query: { op: "move", region: opts.region },
166
+ body: { newPath: opts.newPath }
167
+ });
168
+ },
169
+ /** Retire a secret — owner-only. `DELETE .../<name>?region=<region>` → `204 No Content`. */
170
+ async delete(name, opts) {
171
+ return request(config, {
172
+ method: "DELETE",
173
+ path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),
174
+ query: { region: opts.region }
175
+ });
176
+ }
177
+ }
178
+ };
179
+ }
180
+
181
+ // src/client-factory.ts
182
+ function createKiboClient(config) {
183
+ return {
184
+ vault: makeVaultNamespace(config)
185
+ };
186
+ }
187
+
188
+ // src/crypto.ts
189
+ import { KError as KError2 } from "@k9o/core/errors";
190
+ var cachedWasm;
191
+ function setZkWasm(mod) {
192
+ cachedWasm = mod;
193
+ }
194
+ async function loadWasm() {
195
+ if (cachedWasm) return cachedWasm;
196
+ const pkg = ["..", "wasm", "kibo_kms_rest_ffi.js"].join("/");
197
+ try {
198
+ cachedWasm = await import(pkg);
199
+ } catch {
200
+ throw new KError2({
201
+ code: "KIBO_WASM_ERROR",
202
+ message: "the Kibo zero-knowledge core (wasm) is not bundled in this build of @k9o/kibo; encrypt and decrypt are unavailable",
203
+ context: {},
204
+ recommendation: "Install a release of @k9o/kibo that ships the core, or load it yourself."
205
+ });
206
+ }
207
+ return cachedWasm;
208
+ }
209
+ async function encrypt(input) {
210
+ const wasm = await loadWasm();
211
+ let out;
212
+ try {
213
+ out = await wasm.zk_encrypt(input);
214
+ } catch (e) {
215
+ throw mapZkError(e);
216
+ }
217
+ return { envelope: toBytes(out.envelope) };
218
+ }
219
+ async function decrypt(input) {
220
+ const wasm = await loadWasm();
221
+ let out;
222
+ try {
223
+ out = await wasm.zk_decrypt(input);
224
+ } catch (e) {
225
+ throw mapZkError(e);
226
+ }
227
+ return { plaintext: toBytes(out.plaintext) };
228
+ }
229
+ function toBytes(v) {
230
+ if (v instanceof Uint8Array) return v;
231
+ if (Array.isArray(v)) return Uint8Array.from(v);
232
+ throw new KError2({
233
+ code: "KIBO_WASM_DECODE_ERROR",
234
+ message: "ZK core returned a non-byte value where bytes were expected",
235
+ context: {}
236
+ });
237
+ }
238
+ function mapZkError(e) {
239
+ if (e instanceof KError2) return e;
240
+ const raw = e instanceof Error ? e.message : String(e);
241
+ const head = /^([A-Z][A-Z0-9_]*):\s*([\s\S]*)$/.exec(raw);
242
+ const code = head?.[1] ?? "KIBO_WASM_ERROR";
243
+ let message = head?.[2] ?? raw;
244
+ let context = {};
245
+ const pv = /\(dimension:\s*([^,]+),\s*requested:\s*([^,]+),\s*declared:\s*([^)]+)\)\s*$/.exec(message);
246
+ if (pv) {
247
+ context = { dimension: pv[1].trim(), requested: pv[2].trim(), declared: pv[3].trim() };
248
+ message = message.slice(0, pv.index).trim();
249
+ }
250
+ return new KError2({ code, message, context });
251
+ }
252
+ export {
253
+ createKiboClient,
254
+ decrypt,
255
+ encrypt,
256
+ makeVaultNamespace,
257
+ setZkWasm
258
+ };
259
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client-factory.ts","../src/vault.ts","../src/crypto.ts"],"sourcesContent":["/**\n * `createKiboClient(config)` — per-instance Kibo (ZK vault) SDK factory.\n *\n * Composes into `@k9o/core` as `client.kibo` (re-export, available when a\n * project is bound — the same composition pattern as `@k9o/gate`). Reuses the\n * core HTTP layer (`@k9o/core/http`) so the bearer/header/retry contract is\n * identical to the rest of the SDK pool.\n */\n\nimport { type HttpClientConfig } from \"@k9o/core/http\";\nimport { makeVaultNamespace } from \"./vault.ts\";\n\n/** Shape of the per-instance client returned by `createKiboClient`. */\nexport type KiboClient = {\n /** Vault surface — `client.kibo.vault.zkDeks.{store,fetch}` (F.5). */\n vault: ReturnType<typeof makeVaultNamespace>;\n};\n\n/** Construct a Kibo client bound to the supplied (core) HTTP config. */\nexport function createKiboClient(config: HttpClientConfig): KiboClient {\n return {\n vault: makeVaultNamespace(config),\n };\n}\n","/**\n * `client.kibo.vault.*` — the Kibo vault surface.\n *\n * `vault.zkDeks.{store,fetch}` — member-plane,\n * project-scoped storage of the opaque customer-wrapped DEK envelope. Zero\n * crypto SDK-side: this is a plain authenticated REST round-trip carrying an\n * opaque blob (the wrapping happens in the ZK core, piece C). The encryption\n * surface (`kibo.encrypt`/`decrypt`) is provided by the ZK core binding when it is\n * bundled.\n */\n\nimport { request, type HttpClientConfig } from \"@k9o/core/http\";\nimport { projectPath } from \"@k9o/core/url-grammar\";\nimport { KError } from \"@k9o/core/errors\";\nimport type { Envelope } from \"@k9o/core/envelope\";\nimport type {\n StoreZkDekInput, ZkDekHandle, ZkDekRecord,\n CreateSecretInput, SecretSummary, ListSecretsInput, ListSecretsResult,\n RevealChallenge, RevealSecretResult, UpdateSecretInput, UpdateSecretResult,\n RotateSecretResult, MoveSecretResult,\n} from \"./types.ts\";\n\n/** UTF-8-safe base64 encode, usable across browser/Node/Bun (unlike `Buffer`) — the vault-secrets wire\n * `value` field is base64 (live-verified; the OpenAPI \"plaintext to seal\" description does not mean\n * raw-on-the-wire). */\nfunction encodeBase64Utf8(plaintext: string): string {\n return btoa(unescape(encodeURIComponent(plaintext)));\n}\n\n/** Inverse of {@link encodeBase64Utf8} — decodes a revealed wire `value` back to plaintext. */\nfunction decodeBase64Utf8(b64: string): string {\n return decodeURIComponent(escape(atob(b64)));\n}\n\n/** Both `vault.zkDeks` and `vault.secrets` require a project context (member-plane, /). */\nfunction requireProjectSlug(config: HttpClientConfig): string {\n if (config.projectSlug === undefined || config.projectSlug.length === 0) {\n throw new KError({\n code: \"K9O_MISSING_PROJECT_CONTEXT\",\n message: \"client.kibo.vault requires a bound projectSlug (member-plane resource)\",\n context: {},\n recommendation: \"Pass projectSlug when constructing the client.\",\n });\n }\n return config.projectSlug;\n}\n\nexport function makeVaultNamespace(config: HttpClientConfig) {\n return {\n /** ZK-DEK opaque store/fetch (F.5). */\n zkDeks: {\n /**\n * Store an opaque customer-wrapped DEK envelope.\n * `POST /@<projectSlug>/vault/zk-deks` → the `zkdek_<base62>` handle.\n * The SDK ships the envelope verbatim; it is never parsed here.\n */\n async store(input: StoreZkDekInput): Promise<Envelope<ZkDekHandle>> {\n return request<ZkDekHandle>(config, {\n method: \"POST\",\n path: projectPath(requireProjectSlug(config), \"vault/zk-deks\"),\n body: input,\n });\n },\n\n /**\n * Fetch a stored `WrappedDek` by its handle.\n * `GET /@<projectSlug>/vault/zk-deks/<id>` → the opaque envelope + the\n * non-secret `provider`/`keyVersionRef` the caller needs to unwrap it.\n */\n async fetch(id: string): Promise<Envelope<ZkDekRecord>> {\n return request<ZkDekRecord>(config, {\n method: \"GET\",\n path: projectPath(requireProjectSlug(config), `vault/zk-deks/${encodeURIComponent(id)}`),\n });\n },\n },\n\n /**\n * typed secrets surface (`services/gateway/src/routes/vault-secrets.ts`) — the full family:\n * list/get/create/revealChallenge/reveal/update/rotate/move/delete. Every operation on a NAMED\n * secret (everything except `list`) requires `region` — live-verified against staging, not\n * documented in the route's OpenAPI schema. `list` is the one exception (verified it does NOT\n * need `region`).\n *\n * Response shapes for `update`/`rotate`/`move` are typed to what the gateway ACTUALLY returns\n * (live-verified), not the OpenAPI's documented (and inaccurate for these three) `SecretSummary` —\n * see the 🔴 notes on `UpdateSecretResult`/`RotateSecretResult`/`MoveSecretResult` in `types.ts`.\n */\n secrets: {\n /** List secrets (metadata only — never lists ciphertext). `GET /@<projectSlug>/vault/secrets`.\n * The one secrets operation that does NOT need `region` (live-verified). */\n async list(input?: ListSecretsInput): Promise<Envelope<ListSecretsResult>> {\n return request<ListSecretsResult>(config, {\n method: \"GET\",\n path: projectPath(requireProjectSlug(config), \"vault/secrets\"),\n query: { prefix: input?.prefix, cursor: input?.cursor, limit: input?.limit },\n });\n },\n\n /**\n * Read a secret's metadata (never its value — use `revealChallenge`+`reveal` for that).\n * `GET /@<projectSlug>/vault/secrets/<name>?region=<region>`.\n *\n * 🔴 KNOWN LIVE BUG (staging, 2026-09-05): this call currently fails with\n * `K9O_REVEAL_CHALLENGE_REQUIRED` on every attempt — the gateway/kibo does not honor the\n * documented \"no `X-K9O-Reveal-Challenge` header ⇒ return metadata\" behavior; it demands a\n * challenge unconditionally. Implemented per the documented contract (this is a backend defect,\n * not a client workaround); `list({prefix: exactName})` is the current working alternative for a\n * single secret's metadata until the gateway/kibo side is fixed.\n */\n async get(name: string, opts: { region: string }): Promise<Envelope<SecretSummary>> {\n return request<SecretSummary>(config, {\n method: \"GET\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { region: opts.region },\n });\n },\n\n /**\n * Create a secret under the caller's own auth.\n * `POST /@<projectSlug>/vault/secrets/<name>?region=<region>` → the `sec_<base62>` summary.\n *\n * 🔴 `region` is REQUIRED on the query string, live-verified against staging — the vault-forward\n * proxy fail-closes with `K9O_INVALID_FIELD_VALUE` (\"this request requires an authoritative\n * region\") without it. Distinct from any `region` carried inside `input.value`'s envelope (e.g.\n * the BYOS aws_sigv4 STS-signing region): this one scopes the vault WRITE itself, mirroring the\n * gateway's `gatewayRegion()` residency guard (region-guard.ts) that closed a 2026-08 wrong-region\n * incident for the audit path — the request-shape unit tests never caught this because they don't\n * exercise a real gateway.\n */\n async create(input: CreateSecretInput): Promise<Envelope<SecretSummary>> {\n const { name, region, value, ...rest } = input;\n return request<SecretSummary>(config, {\n method: \"POST\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { region },\n // Live-verified against staging: the wire `value` MUST be base64 — a raw plaintext string\n // (matching the route's own \"the plaintext to seal\" OpenAPI description literally) is\n // rejected with K9O_INVALID_FIELD_VALUE \"Request body could not be parsed.\" `input.value`\n // stays the caller-facing plaintext; base64 is purely a wire-transport detail handled here.\n body: { ...rest, value: encodeBase64Utf8(value) },\n });\n },\n\n /** Mint a single-use reveal challenge — present it as `X-K9O-Reveal-Challenge` on the\n * immediately-following `reveal()` call. `POST .../<name>?op=reveal-challenge&region=<region>`. */\n async revealChallenge(name: string, opts: { region: string }): Promise<Envelope<RevealChallenge>> {\n return request<RevealChallenge>(config, {\n method: \"POST\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { op: \"reveal-challenge\", region: opts.region },\n });\n },\n\n /** Reveal a secret's plaintext value using a single-use challenge from `revealChallenge()`.\n * `GET .../<name>?region=<region>` with `X-K9O-Reveal-Challenge`. Decodes the wire's base64\n * `value` back to plaintext (live-verified: the reveal response's `value` is base64, symmetric\n * with `create`'s encode). */\n async reveal(name: string, opts: { region: string; challenge: string }): Promise<Envelope<RevealSecretResult>> {\n const envelope = await request<RevealSecretResult>(config, {\n method: \"GET\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { region: opts.region },\n headers: { \"X-K9O-Reveal-Challenge\": opts.challenge },\n });\n return { ...envelope, data: { ...envelope.data, value: decodeBase64Utf8(envelope.data.value) } };\n },\n\n /** Update a secret's value (bumps version) — owner-only. `PUT .../<name>?region=<region>`.\n * 🔴 Returns only `{id, name, version}` live (see `UpdateSecretResult`), not the full summary\n * the OpenAPI schema documents — call `get()` after if you need the rest. */\n async update(name: string, input: UpdateSecretInput): Promise<Envelope<UpdateSecretResult>> {\n return request<UpdateSecretResult>(config, {\n method: \"PUT\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { region: input.region },\n body: { value: encodeBase64Utf8(input.value), ...(input.metadata !== undefined ? { metadata: input.metadata } : {}) },\n });\n },\n\n /** Rotate a secret's wrapping key (re-wraps under a fresh `kid`; content unchanged) — owner-only.\n * `POST .../<name>?op=rotate&region=<region>`. */\n async rotate(name: string, opts: { region: string }): Promise<Envelope<RotateSecretResult>> {\n return request<RotateSecretResult>(config, {\n method: \"POST\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { op: \"rotate\", region: opts.region },\n });\n },\n\n /** Move (rename) a secret's hierarchical path — owner-only.\n * `POST .../<name>?op=move&region=<region>`. */\n async move(name: string, opts: { region: string; newPath: string }): Promise<Envelope<MoveSecretResult>> {\n return request<MoveSecretResult>(config, {\n method: \"POST\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { op: \"move\", region: opts.region },\n body: { newPath: opts.newPath },\n });\n },\n\n /** Retire a secret — owner-only. `DELETE .../<name>?region=<region>` → `204 No Content`. */\n async delete(name: string, opts: { region: string }): Promise<Envelope<void>> {\n return request<void>(config, {\n method: \"DELETE\",\n path: projectPath(requireProjectSlug(config), `vault/secrets/${encodeURIComponent(name)}`),\n query: { region: opts.region },\n });\n },\n },\n };\n}\n","/**\n * ZK encrypt/decrypt — the thin TS wrapper over the bound crypto core\n * (`kibo-kms-rest-ffi`, piece C) compiled to wasm. ZERO crypto here: every\n * wrap/unwrap, envelope framing, posture-floor enforcement, and KMS round-trip\n * lives in the audited Rust core. This layer only marshals the typed input\n * across the wasm boundary and maps the core's error string → `KError`.\n *\n * The core exposes `zk_encrypt`/`zk_decrypt` (async) taking/returning plain JS\n * objects via serde-wasm-bindgen, and rejecting with the `ZkFfiError` display\n * string (`\"<K9O_CODE>: <message>\"`, optionally with a posture-violation tail).\n *\n * Composes into `@k9o/core` as `client.kibo.encrypt`/`decrypt`; the F.5\n * `vault.zkDeks.{store,fetch}` surface (envelope persistence) is separate +\n * decoupled (the core never sees the store).\n */\n\nimport { KError } from \"@k9o/core/errors\";\nimport type {\n KiboEncryptInput,\n KiboEncryptOutput,\n KiboDecryptInput,\n KiboDecryptOutput,\n} from \"./crypto-types.ts\";\n\n/** The minimal surface the bound ZK-core wasm exposes. */\nexport interface ZkWasm {\n zk_encrypt(input: unknown): Promise<unknown>;\n zk_decrypt(input: unknown): Promise<unknown>;\n}\n\nlet cachedWasm: ZkWasm | undefined;\n\n/**\n * Inject a pre-loaded core wasm module. Hosts that bundle the wasm themselves\n * (browser/RN, or a test) call this; otherwise `encrypt`/`decrypt` lazy-load\n * the vendored per-provider artifact.\n */\nexport function setZkWasm(mod: ZkWasm): void {\n cachedWasm = mod;\n}\n\n/**\n * Lazily load the bound core wasm. ONE all-provider artifact is generated from\n * `kibo-kms-rest-ffi` (the core compiles every v2 KMS provider in; the\n * `provider` input field selects at call time), vendored under `wasm/` by the\n * publish pipeline and gitignored in-repo. The specifier is assembled at\n * runtime so the bundler/typechecker must not hard-resolve it — the contract\n * is the `ZkWasm` interface above.\n */\nasync function loadWasm(): Promise<ZkWasm> {\n if (cachedWasm) return cachedWasm;\n const pkg = [\"..\", \"wasm\", \"kibo_kms_rest_ffi.js\"].join(\"/\");\n try {\n cachedWasm = (await import(pkg)) as unknown as ZkWasm;\n } catch {\n // A package published without its native core (no bundle at publish time). Say so; never surface a bare\n // module-resolution error, and do not cache the failure.\n throw new KError({\n code: \"KIBO_WASM_ERROR\",\n message: \"the Kibo zero-knowledge core (wasm) is not bundled in this build of @k9o/kibo; encrypt and decrypt are unavailable\",\n context: {},\n recommendation: \"Install a release of @k9o/kibo that ships the core, or load it yourself.\",\n });\n }\n return cachedWasm;\n}\n\n/**\n * Encrypt `input.plaintext` via the customer KMS, client-side. Returns the\n * opaque ZKFE envelope — store it via `vault.zkDeks.store` (F.5) or keep it\n * yourself; it is meaningless to the platform.\n */\nexport async function encrypt(input: KiboEncryptInput): Promise<KiboEncryptOutput> {\n const wasm = await loadWasm();\n let out: unknown;\n try {\n out = await wasm.zk_encrypt(input);\n } catch (e) {\n throw mapZkError(e);\n }\n return { envelope: toBytes((out as { envelope?: unknown }).envelope) };\n}\n\n/**\n * Decrypt a ZKFE `input.envelope`. `strategy`, `attestation_tier`, and\n * `encryption_context` MUST match the values used at encrypt — they are AAD-bound\n * and never recovered from the envelope (anti-substitution discipline).\n */\nexport async function decrypt(input: KiboDecryptInput): Promise<KiboDecryptOutput> {\n const wasm = await loadWasm();\n let out: unknown;\n try {\n out = await wasm.zk_decrypt(input);\n } catch (e) {\n throw mapZkError(e);\n }\n return { plaintext: toBytes((out as { plaintext?: unknown }).plaintext) };\n}\n\n/** Normalise wasm byte output (serde-wasm-bindgen emits `Vec<u8>` as a number\n * array; some hosts return a `Uint8Array`) to `Uint8Array`. */\nfunction toBytes(v: unknown): Uint8Array {\n if (v instanceof Uint8Array) return v;\n if (Array.isArray(v)) return Uint8Array.from(v as number[]);\n throw new KError({\n code: \"KIBO_WASM_DECODE_ERROR\",\n message: \"ZK core returned a non-byte value where bytes were expected\",\n context: {},\n });\n}\n\n/**\n * Map the core's rejected error → `KError`. The wasm path flattens `ZkFfiError`\n * to its display string: `\"<CODE>: <message>\"` where `<CODE>` is a `K9O_*` wire\n * code (or `UPSTREAM_KMS_ERROR` for the customer's own KMS failures), optionally\n * followed by `\"(dimension: …, requested: …, declared: …)\"` for a posture-floor\n * violation. Codes are passed through (never hardcoded), per the KError discipline.\n */\nfunction mapZkError(e: unknown): KError {\n if (e instanceof KError) return e;\n const raw = e instanceof Error ? e.message : String(e);\n const head = /^([A-Z][A-Z0-9_]*):\\s*([\\s\\S]*)$/.exec(raw);\n const code = head?.[1] ?? \"KIBO_WASM_ERROR\";\n let message = head?.[2] ?? raw;\n\n let context: Record<string, unknown> = {};\n const pv = /\\(dimension:\\s*([^,]+),\\s*requested:\\s*([^,]+),\\s*declared:\\s*([^)]+)\\)\\s*$/.exec(message);\n if (pv) {\n context = { dimension: pv[1]!.trim(), requested: pv[2]!.trim(), declared: pv[3]!.trim() };\n message = message.slice(0, pv.index).trim();\n }\n return new KError({ code, message, context });\n}\n"],"mappings":"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","names":["KError"]}