k9o 1.0.0 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7181cb157e2075ffed56c186db0de091dc3bffb8e87ed498451e3b4dc4629e9f
4
- data.tar.gz: 41415d026e53bea0e505e702b5fefe58200a26092ae3176c684385bd49bad18d
3
+ metadata.gz: d8266cd8220381fff27135c8ef7bdcdc6432bdaf90a98ce31ce710f1eb583882
4
+ data.tar.gz: b5110855f5acd547d18180eab1b6d22a00ae25d7de1b441411ed4d2ee54cd2e2
5
5
  SHA512:
6
- metadata.gz: ea526dce965974039710f5ab14776ac274271793e0ea95ac979d46a51bba7ab5b552e418a0401fc8cf138ddaade8e169f13ca96df9b4bac51a3d491e2a0f7acb
7
- data.tar.gz: bed73f779902b19472006ad86eac056c8a47f89da96c94675a70f201fdfbdd6dd1e5aaf5a2e15e2a59f0bfb4e4b9024b2b61e078696e8dd144e8e36af305af2e
6
+ metadata.gz: d3d7559ed789b15ae5bf26aecf6abe623c52794cd48685d6471605c21acf73f21a73a233d80ec9cf0de6e5d6423a00f51bf1142e5e5a2045a3ba9025df08bcf7
7
+ data.tar.gz: 3a14bb7e47092c45c34e350c1029598ae0ee056a58c06519c4270487ac88951a491fba6f8731d947233cc08ca166502d3f741f3faa3d0f241cd39979e3560c73
data/CHANGELOG.md CHANGED
@@ -1,38 +1,14 @@
1
1
  # Changelog — k9o (Ruby)
2
2
 
3
- ## Unreleased
3
+ ## 1.1.1 — 2026-10-25
4
4
 
5
- - `client.storage` buckets and objects — flat methods `create_bucket(name, ...)` / `get_bucket` / `list_buckets` / `update_bucket(name, patch)` / `delete_bucket(name, empty: false)` against `/@<slug>/storage/buckets[/<bucket>]` (`?empty=true` sent only when `empty: true`), and `storage.from(bucket)` handles with `upload(path, data, content_type:, upsert:, metadata:)` (a real `multipart/form-data` body built with the stdlib; the transport no longer forces a JSON content type for it), `create_signed_url(path, expires_in:, download:)`, `list(prefix:)` and `remove(path)`. `expires_in` is required, an Integer 1..604800, refused client-side with `K9O_INVALID_FIELD_VALUE` before any request; no default. Bucket and path values are always URL-encoded and never rewritten. No signed-PUT upload URL and no copy (no gateway route). Requires a bound `project_slug`. Adds `K9o::Storage` and `K9o::Multipart`; `HttpTransport.request(multipart:)`.
6
- - `client.gate.hosted` — `GET /@<slug>/gate/hosted`; returns the envelope `{ 'signInUrl', 'rpId' }` for the project's hosted sign-in page. Unauthenticated: no `Authorization` or `Cookie` header is sent even when `api_key` is configured. An unknown org, a deleted project and a non-Gate project all surface the same 404 `K9O_PROJECT_NOT_FOUND`. Requires a bound `project_slug`. Adds `HttpTransport.request(authenticated: false)`.
7
- - `client.ai.embed(input:, model: nil)` — `POST /@<slug>/ai/embeddings`; `input` is one string or an array of strings, sent exactly as given; `model` is omitted from the body when not given. Requires a bound `project_slug` (`K9O_MISSING_PROJECT_CONTEXT` otherwise). The input text never appears in an SDK-constructed error. Adds `K9o::Ai`.
5
+ - Documentation links corrected: the documentation hub is https://docs.kilimanjaro.dev, with the website, platform API and console listed in a Links section. Package metadata points at the same places.
8
6
 
9
- ## v0.1.0 — 2026-05-26 (P3 wave 7 — Ruby idiomatic reshape; FINAL P3 WAVE)
7
+ ## 1.1.0 — 2026-10-25
10
8
 
11
- **Reshape** of `packages/ruby` from prior OpenAPI-generated `k9o-gate@0.3.0` raw client (214-file output; wrong gem name; not idiomatic) to hand-authored idiomatic `k9o` gem.
9
+ - Documentation rewritten with runnable examples and expected output; internal cross-references removed from the published sources. No change to the public API.
10
+ - Error text for `update()` / `delete()` without an `id` filter no longer mentions a version or a roadmap.
12
11
 
13
- NEW surfaces:
12
+ ## 1.0.0 — 2026-10-23
14
13
 
15
- - `K9o.create_client(base_url:, api_key:, org_slug:, project_slug:, ...)` factory + baseUrl validation (keyword arguments per Ruby idiom)
16
- - `K9o::KError < StandardError` — `.code` / `.message` / `.context` (frozen) / `.recommendation` / `.status` / `.request_id` readers; `#message` overridden to return raw text (avoids infinite recursion with `#to_s` override); `with_recommendation` helper
17
- - `K9o::Envelope` + `K9o::Meta` with 6 typed sub-accessor classes (`MetaCursor` / `MetaSubscription` Struct / `MetaIdempotency` Struct / `MetaWarning` Struct / `MetaTiming` Struct / `MetaContext` Struct); `from_wire` constructs from gateway JSON
18
- - `K9o::UrlGrammar.{validate_base_url, validate_slug, project_path, org_path, platform_path}` module functions; raises KError on violation
19
- - Data-plane DSL `client.from('collection')` chainable filter builder (11 ops: eq / neq / gt / gte / lt / lte / like / ilike / is + `in_(col, [...])` / `not_in` + generic `filter`) + `.limit(n)` / `.cursor(s)` / `.count(mode)` + `.execute` terminal; insert/update/delete with `.eq("id", ...)` discipline
20
- - `client.projects.{list, create(slug:, name:), get(slug), update(slug, name:)}` (keyword args)
21
- - `client.gate.{sign_up(email:, password:), sign_in(email:, password:), sign_out(refresh_token:), whoami, refresh_token(refresh_token:), verify_session}` (project-scoped; keyword args)
22
- - HTTP layer: `Net::HTTP` stdlib; KError rehydration on non-2xx; transport failure → K9O_UPSTREAM_UNAVAILABLE; malformed envelope → K9O_INTERNAL_ERROR; injectable `http_client:` for tests
23
-
24
- **Tests:** 21 pass / 54 assertions / 0 fail (`ruby test/*.rb` against system Ruby 2.6; gem targets 3.2+ per ch13 spec):
25
- - 5 KErrorTest (construct + raisable + to_s with status + with_recommendation + from_wire rehydration)
26
- - 8 UrlGrammarTest (accepts/rejects + path builders)
27
- - 8 ClientTest (construct + normalise + reject + DSL select/update requirements + projects + gate + collection validation)
28
-
29
- **Dependencies:** Ruby 3.2+ runtime; stdlib only (`Net::HTTP`, `json`, `uri`).
30
- **Dev:** minitest 5.20.
31
-
32
- Dropped Ruby from `openapitools.json` + `package.json` `sdks:generate:ruby` — hand-authored against `services/gateway/openapi.json` contract going forward.
33
-
34
- **P3 7-wave reshape COMPLETE.** All 7 server SDKs (Python + Go + Rust + Java + .NET + PHP + Ruby) shipped as idiomatic per-language reshapes.
35
-
36
- ---
37
-
38
- **Prior history**: `k9o-gate@0.3.0` OpenAPI-generator output retired at this version.
14
+ First public release. See the README for the full API overview.
data/README.md CHANGED
@@ -1,67 +1,549 @@
1
- # k9o — Kilimanjaro platform SDK (Ruby)
1
+ # k9o
2
2
 
3
- Idiomatic Ruby SDK. `snake_case` methods; raise `K9o::KError`; keyword arguments; Net::HTTP stdlib transport.
3
+ The Kilimanjaro platform SDK for Ruby.
4
4
 
5
- ## Status
5
+ ## Contents
6
6
 
7
- v0.1.0 — first-pass idiomatic ship (P3 wave 7; reshape from prior `k9o-gate@0.3.0` OpenAPI codegen).
7
+ - [Links](#links)
8
+ - [Install](#install)
9
+ - [Quick start](#quick-start)
10
+ - [Authentication and project context](#authentication-and-project-context)
11
+ - [Running queries](#running-queries)
12
+ - [Handling errors](#handling-errors)
13
+ - [Appendix](#appendix)
14
+ - [License](#license)
8
15
 
9
- ## Install (when published to RubyGems)
16
+ ## Links
17
+
18
+ - Website: <https://kilimanjaro.dev>
19
+ - Documentation / Developer Hub: <https://docs.kilimanjaro.dev>
20
+ - Platform API: <https://api.k9o.io>
21
+ - Platform Console: <https://console.k9o.io>
22
+
23
+ ## Install
10
24
 
11
25
  ```bash
12
26
  gem install k9o
13
27
  ```
14
28
 
29
+ Or add it to your `Gemfile`:
30
+
31
+ ```ruby
32
+ gem "k9o"
33
+ ```
34
+
35
+ Requires Ruby 3.2 or newer. See [requirements](#requirements) for details.
36
+
15
37
  ## Quick start
16
38
 
39
+ The examples use a `tasks` collection with `title` and `done` fields.
40
+
41
+ ### Create the client
42
+
17
43
  ```ruby
18
- require 'k9o'
44
+ require "k9o"
19
45
 
20
46
  k9o = K9o.create_client(
21
- base_url: "https://acme.api.k9o.io",
22
- api_key: ENV["K9O_API_KEY"],
23
47
  org_slug: "acme",
24
- project_slug: "member-portal"
48
+ project_slug: "task-app",
49
+ api_key: ENV.fetch("K9O_API_KEY")
50
+ )
51
+ ```
52
+
53
+ ### Add a task
54
+
55
+ ```ruby
56
+ new_task = { "title" => "Write the README", "done" => false }
57
+ created = k9o.from("tasks").insert(new_task)
58
+ puts "created: #{created.data['title']}"
59
+ ```
60
+
61
+ ```text
62
+ created: Write the README
63
+ ```
64
+
65
+ ### List tasks
66
+
67
+ ```ruby
68
+ response = k9o.from("tasks").select.eq("done", false).limit(10).execute
69
+ response.data.each do |task|
70
+ puts "#{task['title']} #{task['done']}"
71
+ end
72
+ ```
73
+
74
+ ```text
75
+ Write the README false
76
+ ```
77
+
78
+ ### Update and delete a task
79
+
80
+ Both calls need an `eq("id", ...)` filter.
81
+
82
+ ```ruby
83
+ task_id = created.data["id"]
84
+
85
+ patch = { "done" => true }
86
+ k9o.from("tasks").update(patch).eq("id", task_id).execute
87
+
88
+ k9o.from("tasks").delete.eq("id", task_id).execute
89
+ ```
90
+
91
+ ## Authentication and project context
92
+
93
+ The client needs a key and, for project calls, an org and project.
94
+
95
+ | Option | What it does |
96
+ |---|---|
97
+ | `api_key:` | Bearer token sent with every request. |
98
+ | `org_slug:` | Organization. On the default host the SDK uses `https://<org_slug>.api.k9o.io`. |
99
+ | `project_slug:` | Project. Required by every project-scoped namespace. |
100
+
101
+ See [client options](#client-options) for every option.
102
+
103
+ ### Choose a host
104
+
105
+ Pick one of two forms.
106
+
107
+ - Default platform host: pass the org slug, project slug and key.
108
+ - Custom or self-hosted host: pass `base_url`, project slug and key, and no org slug.
109
+
110
+ ```ruby
111
+ k9o = K9o.create_client(
112
+ base_url: "https://k9o.internal.example.com",
113
+ project_slug: "task-app",
114
+ api_key: ENV.fetch("K9O_API_KEY")
25
115
  )
116
+ ```
117
+
118
+ The base URL rules are listed under [regional hosts](#regional-hosts).
26
119
 
120
+ ## Running queries
121
+
122
+ Chain filters on `select`, then call `execute`. The result carries rows in `data` and details in `meta`.
123
+
124
+ | Call | What it does |
125
+ |---|---|
126
+ | `eq(column, value)` | Keep rows where the column equals the value. |
127
+ | `limit(n)` | Return at most `n` rows. |
128
+ | `cursor(token)` | Continue from `meta.cursor.next`. |
129
+
130
+ See [filters](#filters) and [paging](#paging) for all calls, and [response metadata](#response-metadata) for every `meta` field.
131
+
132
+ A sub-object the server did not send is `nil`, so use `&.` when it may be absent.
133
+
134
+ ```ruby
135
+ request_id = response.meta.context.request_id
136
+ total = response.meta.cursor.total_count
137
+ puts "#{request_id} #{total}"
138
+ ```
139
+
140
+ ```text
141
+ req_01H... 1
142
+ ```
143
+
144
+ ## Handling errors
145
+
146
+ Failures raise `K9o::KError`, a subclass of `StandardError`. Branch on `code`.
147
+
148
+ ```ruby
27
149
  begin
28
- response = k9o.from("posts").select.limit(10).execute
29
- response.data.each { |row| puts row }
30
- puts "next cursor: #{response.meta.cursor&.next}"
31
-
32
- session = k9o.gate.sign_in(email: "u@x.com", password: "...")
33
- puts "signed in: #{session.data['user']['id']}"
34
- rescue K9o::KError => e
35
- warn "[#{e.code}] #{e.message}: #{e.recommendation}"
36
- raise
150
+ k9o.from("missing").select.execute
151
+ rescue K9o::KError => error
152
+ puts "#{error.code} #{error.status} #{error.request_id}"
153
+ puts error.message
37
154
  end
38
155
  ```
39
156
 
40
- ## Idiomatic shape (per ch13)
157
+ ```text
158
+ K9O_NOT_FOUND 404 req_01H...
159
+ Collection not found
160
+ ```
161
+
162
+ - See [error attributes](#error-attributes) for every field.
163
+ - See [error codes](#error-codes) for the codes the SDK raises.
164
+ - See [retries](#retries) for automatic retry rules.
165
+
166
+ ## Appendix
167
+
168
+ ### Requirements
169
+
170
+ | Requirement | Version |
171
+ |---|---|
172
+ | `Ruby` | 3.2 or newer |
173
+ | `Runtime gems` | None (uses `Net::HTTP`, `json` and `uri` from the standard library) |
174
+
175
+ ### Client options
176
+
177
+ | Option | What it does |
178
+ |---|---|
179
+ | `api_key:` | Bearer token sent with every request. |
180
+ | `org_slug:` | Organization. On the default host the SDK uses `https://<org_slug>.api.k9o.io`. |
181
+ | `project_slug:` | Project. Required by every project-scoped namespace. |
182
+ | `base_url:` | Scheme and host only. Defaults to `https://api.k9o.io`. |
183
+ | `default_headers:` | Extra headers added to every request. |
184
+ | `http_client:` | A `Net::HTTP`-compatible object used instead of the default connection. |
185
+
186
+ `org_slug` and `project_slug` are also sent as the `x-k9o-org-slug` and `x-k9o-project-slug` headers.
187
+
188
+ ### Methods by namespace
189
+
190
+ Every method is called on the client, for example `k9o.projects.list`. Return values are `Envelope` objects.
191
+
192
+ #### Data
193
+
194
+ `k9o.from(collection)` reads and writes rows in one collection of the active project.
195
+
196
+ | Method | What it does |
197
+ |---|---|
198
+ | `select` | Start a query. Finish with `execute`. |
199
+ | `insert(record)` | Add one row and return it. |
200
+ | `update(patch)` | Change one row. Needs `eq("id", ...)`. |
201
+ | `delete` | Remove one row. Needs `eq("id", ...)`. |
202
+
203
+ ##### Filters
204
+
205
+ Chain filters before `execute`. Values are matched against one column.
206
+
207
+ | Method | What it does |
208
+ |---|---|
209
+ | `eq(column, value)` | Equal to value. |
210
+ | `neq(column, value)` | Not equal to value. |
211
+ | `gt(column, value)` | Greater than value. |
212
+ | `gte(column, value)` | Greater than or equal. |
213
+ | `lt(column, value)` | Less than value. |
214
+ | `lte(column, value)` | Less than or equal. |
215
+ | `in_(column, values)` | Equal to any value in the list. |
216
+ | `not_in(column, values)` | Equal to none of the values. |
217
+ | `like(column, pattern)` | Case-sensitive pattern match. |
218
+ | `ilike(column, pattern)` | Case-insensitive pattern match. |
219
+ | `is(column, value)` | Match `null`, `true` or `false`. |
220
+ | `filter(column, op, value)` | Generic form with an explicit operator name. |
221
+
222
+ ##### Paging
223
+
224
+ | Method | What it does |
225
+ |---|---|
226
+ | `limit(n)` | Maximum rows to return. |
227
+ | `cursor(token)` | Continue from `meta.cursor.next`. |
228
+ | `count(mode)` | Row count mode: `none`, `exact` or `estimated`. |
229
+
230
+ #### Projects
231
+
232
+ `k9o.projects` manages projects in the active organization.
233
+
234
+ | Method | What it does |
235
+ |---|---|
236
+ | `k9o.projects.list` | List projects you can access. |
237
+ | `k9o.projects.create` | Create a project from `slug` and `name`. |
238
+ | `k9o.projects.get` | Read a project by slug. |
239
+ | `k9o.projects.update` | Change a project's `name`. |
240
+
241
+ #### Gate (end-user sign-in)
242
+
243
+ `k9o.gate` signs in the active project's end users and needs `project_slug`.
244
+
245
+ | Method | What it does |
246
+ |---|---|
247
+ | `k9o.gate.sign_up` | Create an end user from email and password. |
248
+ | `k9o.gate.sign_in` | Sign in with email and password. |
249
+ | `k9o.gate.sign_out` | Revoke the session's refresh token. |
250
+ | `k9o.gate.whoami` | Return the signed-in identity. |
251
+ | `k9o.gate.refresh_token` | Exchange a refresh token for a new access token. |
252
+ | `k9o.gate.verify_session` | Check that the current session is valid. |
253
+ | `k9o.gate.hosted` | Return the hosted sign-in `signInUrl` and `rpId`. |
254
+
255
+ ```ruby
256
+ session = k9o.gate.sign_in(email: "ada@example.com", password: "correct-horse")
257
+ user = session.data["user"]
258
+ puts user["email"]
259
+ ```
260
+
261
+ ```text
262
+ ada@example.com
263
+ ```
264
+
265
+ #### Storage
266
+
267
+ `k9o.storage` manages buckets and the objects inside them.
268
+
269
+ ##### Buckets
270
+
271
+ | Method | What it does |
272
+ |---|---|
273
+ | `k9o.storage.create_bucket` | Create a bucket by name. |
274
+ | `k9o.storage.get_bucket` | Read one bucket. |
275
+ | `k9o.storage.list_buckets` | List buckets. |
276
+ | `k9o.storage.update_bucket` | Change bucket settings. |
277
+ | `k9o.storage.delete_bucket` | Delete a bucket. Pass `empty` to purge its objects first. |
278
+
279
+ ##### Objects
280
+
281
+ `k9o.storage.from(bucket)` returns a handle for one bucket.
282
+
283
+ | Method | What it does |
284
+ |---|---|
285
+ | `k9o.storage.from(bucket).upload` | Store bytes at a path. Existing paths are kept unless `upsert` is true. |
286
+ | `k9o.storage.from(bucket).create_signed_url` | Create a time-limited download link. |
287
+ | `k9o.storage.from(bucket).list` | List objects, optionally under a `prefix`. |
288
+ | `k9o.storage.from(bucket).remove` | Delete the object at a path. |
289
+
290
+ `expires_in` is required, in seconds from 1 to 604800.
291
+
292
+ ```ruby
293
+ avatars = k9o.storage.from("avatars")
294
+ avatars.upload("ada.png", "...image bytes...", content_type: "image/png")
295
+ signed = avatars.create_signed_url("ada.png", expires_in: 300)
296
+ ```
297
+
298
+ #### Functions
299
+
300
+ `k9o.functions` deploys and runs server-side functions.
41
301
 
42
- | Aspect | This SDK |
302
+ | Method | What it does |
43
303
  |---|---|
44
- | Gem name | `k9o` (RubyGems) |
45
- | Module | `K9o` |
46
- | Method casing | `snake_case` |
47
- | Error delivery | `raise K9o::KError < StandardError` |
48
- | Factory pattern | `K9o.create_client(base_url:, api_key:, org_slug:, project_slug:)` (keyword args) |
49
- | Data DSL entry | `client.from('collection')` |
50
- | Filter chain | `.eq(col, val)` / `.gt()` / `.in_(col, [...])` / `.is(col, val)` / `.filter(col, op, val)` |
51
- | Terminal verb | `.execute` (parameterless method chain — Ruby idiom) |
52
- | Meta accessor | `response.meta.cursor&.next` (safe-navigation `&.`); `.meta.timing&.total_ms`; `.meta.context&.request_id` |
53
- | Wire format | Always camelCase JSON; explicit field-name translation in `Envelope.from_wire` |
54
- | Runtime | Ruby 3.2+ (per ch13 §2.1.8 spec) |
55
- | HTTP library | `Net::HTTP` (stdlib; no external deps) |
304
+ | `k9o.functions.deploy` | Deploy a function from `name`, `runtime` and `code`. |
305
+ | `k9o.functions.list` | List functions. |
306
+ | `k9o.functions.get` | Read one function by name. |
307
+ | `k9o.functions.delete` | Remove a function. |
308
+ | `k9o.functions.invoke` | Run a function with a payload. |
56
309
 
57
- ## Architectural notes
310
+ #### Migrations
58
311
 
59
- - **Stdlib only**: uses `Net::HTTP` + `json` + `uri`; no Typhoeus or Faraday.
60
- - **Keyword arguments throughout**: `K9o.create_client(base_url:, api_key:, ...)` and `k9o.gate.sign_in(email:, password:)` per Ruby 3.x idiom.
61
- - **`&.` safe navigation**: caller pattern `response.meta.cursor&.next` (cursor may be nil if gateway omits the sub-namespace).
62
- - **`message` override**: `K9o::KError#message` returns the raw text directly to avoid infinite recursion with `to_s` override (Ruby's `Exception#message` calls `to_s` by default).
63
- - **`.execute` method**: no parens for terminal verb per Ruby convention; chain reads naturally.
312
+ `k9o.migrations` changes the project's schema.
313
+
314
+ | Method | What it does |
315
+ |---|---|
316
+ | `k9o.migrations.apply` | Apply migrations now. |
317
+ | `k9o.migrations.list` | List applied migrations. |
318
+ | `k9o.migrations.get` | Read one migration by version. |
319
+ | `k9o.migrations.queue` | Queue migrations for approval. |
320
+ | `k9o.migrations.list_pending` | List queued migrations. |
321
+ | `k9o.migrations.apply_pending` | Apply one queued migration. |
322
+ | `k9o.migrations.reject_pending` | Reject one queued migration. |
323
+ | `k9o.migrations.delete_pending` | Delete one queued migration. |
324
+
325
+ #### Policies
326
+
327
+ `k9o.policies` manages access policy bundles.
328
+
329
+ | Method | What it does |
330
+ |---|---|
331
+ | `k9o.policies.current` | Read the published bundle. |
332
+ | `k9o.policies.list` | List bundles. |
333
+ | `k9o.policies.create` | Create a bundle from `name` and `rules`. |
334
+ | `k9o.policies.validate` | Check rules without saving. |
335
+ | `k9o.policies.get` | Read one bundle. |
336
+ | `k9o.policies.update` | Change a bundle. |
337
+ | `k9o.policies.delete` | Remove a bundle. |
338
+ | `k9o.policies.publish` | Make a bundle current. |
339
+
340
+ #### Audit
341
+
342
+ `k9o.audit` reads the project's audit events.
343
+
344
+ | Method | What it does |
345
+ |---|---|
346
+ | `k9o.audit.query` | Search events by time range, type and more. |
347
+
348
+ #### AI embeddings
349
+
350
+ `k9o.ai` creates text embeddings.
351
+
352
+ | Method | What it does |
353
+ |---|---|
354
+ | `k9o.ai.embed(input:, model: nil)` | Embed one string or a list of strings. |
355
+
356
+ #### Language models
357
+
358
+ `k9o.compute.llms` lists and calls hosted models.
359
+
360
+ | Method | What it does |
361
+ |---|---|
362
+ | `k9o.compute.llms.list` | List available models. |
363
+ | `k9o.compute.llms.read` | Read one model. |
364
+ | `k9o.compute.llms.invoke` | Send a prompt and get the reply. |
365
+ | `k9o.compute.llms.invoke_stream` | Stream the reply token by token (returns an `Enumerator`). |
366
+
367
+ #### Realtime
368
+
369
+ `k9o.realtime` delivers live events for a topic.
370
+
371
+ | Method | What it does |
372
+ |---|---|
373
+ | `k9o.realtime.subscribe` | Stream live events (returns an `Enumerator`). |
374
+ | `k9o.realtime.replay` | Read past events from a sequence number. |
375
+ | `k9o.realtime.subscribe_poll` | Poll for events from a sequence number. |
376
+
377
+ `K9o::Realtime::Topic` builds topic names, for example `Topic.collection("tasks")`.
378
+
379
+ #### Studio
380
+
381
+ `k9o.studio` manages workflows and dashboards.
382
+
383
+ ##### Workflows
384
+
385
+ | Method | What it does |
386
+ |---|---|
387
+ | `k9o.studio.workflows.list` | List workflows. |
388
+ | `k9o.studio.workflows.create` | Create a workflow. |
389
+ | `k9o.studio.workflows.read` | Read one workflow. |
390
+ | `k9o.studio.workflows.update` | Change a workflow. |
391
+ | `k9o.studio.workflows.delete` | Delete a workflow. |
392
+ | `k9o.studio.workflows.trigger` | Start a run. |
393
+ | `k9o.studio.workflows.runs.list` | List a workflow's runs. |
394
+ | `k9o.studio.workflows.runs.read` | Read one run. |
395
+ | `k9o.studio.workflows.runs.cancel` | Cancel a run. |
396
+
397
+ ##### Dashboards
398
+
399
+ | Method | What it does |
400
+ |---|---|
401
+ | `k9o.studio.dashboards.list` | List dashboards. |
402
+ | `k9o.studio.dashboards.create` | Create a dashboard. |
403
+ | `k9o.studio.dashboards.read` | Read one dashboard. |
404
+ | `k9o.studio.dashboards.update` | Change a dashboard. |
405
+ | `k9o.studio.dashboards.delete` | Delete a dashboard. |
406
+ | `k9o.studio.dashboards.pin` | Pin to the workspace. |
407
+ | `k9o.studio.dashboards.unpin` | Remove from the workspace. |
408
+
409
+ #### Current user
410
+
411
+ `k9o.me` covers the signed-in account.
412
+
413
+ | Method | What it does |
414
+ |---|---|
415
+ | `k9o.me.profile.get` | Read the profile. |
416
+ | `k9o.me.profile.update` | Change the display name. |
417
+ | `k9o.me.sessions.list` | List active sessions. |
418
+ | `k9o.me.sessions.revoke` | End one session. |
419
+ | `k9o.me.sessions.revoke_all` | End all sessions. |
420
+ | `k9o.me.api_tokens.list` | List API tokens. |
421
+ | `k9o.me.api_tokens.create` | Create an API token. |
422
+ | `k9o.me.api_tokens.delete` | Delete an API token. |
423
+ | `k9o.me.notifications.list` | List notifications. |
424
+ | `k9o.me.notifications.mark_read` | Mark one as read. |
425
+ | `k9o.me.notifications.mark_all_read` | Mark all as read. |
426
+ | `k9o.me.audit_log.query` | Search your own audit events. |
427
+ | `k9o.me.data_export.request` | Request a data export. |
428
+ | `k9o.me.data_export.status` | Check an export job. |
429
+
430
+ #### Organization
431
+
432
+ `k9o.orgs` lists organizations and `k9o.org` administers the active one.
433
+
434
+ ##### Organizations
435
+
436
+ | Method | What it does |
437
+ |---|---|
438
+ | `k9o.orgs.list` | List your organizations. |
439
+ | `k9o.orgs.get` | Read one by slug. |
440
+ | `k9o.orgs.current` | Read the active organization. |
441
+ | `k9o.orgs.restore` | Restore a deleted organization. |
442
+
443
+ ##### Administration
444
+
445
+ | Method | What it does |
446
+ |---|---|
447
+ | `k9o.org.get` | Read the active organization. |
448
+ | `k9o.org.members.list` | List members. |
449
+ | `k9o.org.members.invite` | Invite a member by email and role. |
450
+ | `k9o.org.members.get` | Read one member. |
451
+ | `k9o.org.members.remove` | Remove a member. |
452
+ | `k9o.org.groups.list` | List groups. |
453
+ | `k9o.org.groups.create` | Create a group. |
454
+ | `k9o.org.groups.get` | Read one group. |
455
+ | `k9o.org.groups.delete` | Delete a group. |
456
+ | `k9o.org.audit_log.query` | Search organization audit events. |
457
+ | `k9o.org.gate.roles.list` | List role grants. |
458
+ | `k9o.org.gate.roles.grant` | Grant a role to a user. |
459
+ | `k9o.org.gate.roles.get` | Read one grant. |
460
+ | `k9o.org.gate.roles.revoke` | Revoke a grant. |
461
+ | `k9o.org.gate.idp_providers.list` | List identity providers. |
462
+ | `k9o.org.gate.idp_providers.create` | Add an identity provider. |
463
+ | `k9o.org.gate.idp_providers.get` | Read one provider. |
464
+ | `k9o.org.gate.idp_providers.configure` | Change a provider. |
465
+ | `k9o.org.gate.idp_providers.delete` | Remove a provider. |
466
+ | `k9o.org.smtp.get` | Read the mail server settings. |
467
+ | `k9o.org.smtp.set` | Save the mail server settings. |
468
+ | `k9o.org.smtp.test` | Send a test email. |
469
+ | `k9o.org.smtp.unset` | Remove the mail server settings. |
470
+ | `k9o.org.default_llm.get` | Read the default model. |
471
+ | `k9o.org.default_llm.set` | Set the default model. |
472
+
473
+ #### Vault secrets
474
+
475
+ `k9o.kibo.vault.secrets` stores and reveals secrets in the project's vault.
476
+
477
+ | Method | What it does |
478
+ |---|---|
479
+ | `k9o.kibo.vault.secrets.list` | List secrets by prefix. |
480
+ | `k9o.kibo.vault.secrets.get` | Read a secret's details. |
481
+ | `k9o.kibo.vault.secrets.create` | Store a new secret. |
482
+ | `k9o.kibo.vault.secrets.reveal_challenge` | Get a one-time challenge for revealing. |
483
+ | `k9o.kibo.vault.secrets.reveal` | Reveal the value using the challenge. |
484
+ | `k9o.kibo.vault.secrets.update` | Replace the value. |
485
+ | `k9o.kibo.vault.secrets.rotate` | Rotate the secret. |
486
+ | `k9o.kibo.vault.secrets.move` | Move to a new path. |
487
+ | `k9o.kibo.vault.secrets.delete` | Delete the secret. |
488
+
489
+ ### Response metadata
490
+
491
+ | Field | What it holds |
492
+ |---|---|
493
+ | `meta.cursor` | Pagination: `next` and `total_count`. |
494
+ | `meta.context` | Request tracing: `request_id`. |
495
+ | `meta.timing` | Server time: `total_ms`. |
496
+ | `meta.warnings` | List of non-fatal warnings, each with `code` and `message`. |
497
+ | `meta.idempotency` | `replayed` flag for repeated requests. |
498
+ | `meta.subscription` | `is_initial` flag for streamed events. |
499
+ | `meta.cost` | Usage cost details as a hash. |
500
+
501
+ ### Error attributes
502
+
503
+ | Attribute | Meaning |
504
+ |---|---|
505
+ | `code` | Error code such as `K9O_NOT_FOUND`. |
506
+ | `message` | Human-readable explanation. |
507
+ | `recommendation` | Suggested next step, or `nil`. |
508
+ | `status` | HTTP status, or `nil` if no request was made. |
509
+ | `request_id` | Server trace id. Quote it when contacting support. |
510
+ | `context` | Read-only details for the error. |
511
+
512
+ The server may send codes not listed here, so keep a fallback branch.
513
+
514
+ ### Error codes
515
+
516
+ | Code | When |
517
+ |---|---|
518
+ | `K9O_INVALID_BASE_URL` | `base_url` has a path, query or bad scheme. |
519
+ | `K9O_MISSING_PROJECT_CONTEXT` | A project call was made without `project_slug`. |
520
+ | `K9O_INVALID_FIELD_VALUE` | An argument failed validation before sending. |
521
+ | `K9O_UPSTREAM_UNAVAILABLE` | Network failure reaching the gateway. |
522
+ | `K9O_INTERNAL_ERROR` | The response could not be read. |
523
+
524
+ `error.to_s` reads like `[K9O_NOT_FOUND] Collection not found (status=404)`.
525
+
526
+ ### Retries
527
+
528
+ - GET, HEAD, OPTIONS and DELETE are retried on network errors.
529
+ - They are also retried on 429, 502, 503 and 504.
530
+ - The default is 3 retries with exponential backoff.
531
+ - Other methods are never retried.
532
+
533
+ ### Regional hosts
534
+
535
+ - Organization hosts such as `https://acme.api.k9o.io` are region-free.
536
+ - The SDK sends one credential-free `HEAD` request to learn the region.
537
+ - Later requests go to the regional host.
538
+ - Any other base URL is used exactly as given.
539
+
540
+ ### Related packages
541
+
542
+ | Package | What it is |
543
+ |---|---|
544
+ | `@k9o/core` | TypeScript SDK |
545
+ | `@k9o/cli` | Command-line tool |
64
546
 
65
547
  ## License
66
548
 
67
- UNLICENSED — internal to Kilimanjaro.
549
+ Apache-2.0 © Formelo Inc. See `LICENSE` and `NOTICE`.
data/k9o.gemspec CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.metadata = {
27
27
  'homepage_uri' => 'https://kilimanjaro.dev',
28
+ 'documentation_uri' => 'https://docs.kilimanjaro.dev',
28
29
  'source_code_uri' => 'https://github.com/k9o-dev/sdk-ruby',
29
30
  'changelog_uri' => 'https://github.com/k9o-dev/sdk-ruby/blob/main/CHANGELOG.md'
30
31
  }
data/lib/k9o/client.rb CHANGED
@@ -36,7 +36,7 @@ module K9o
36
36
 
37
37
  # Factory — construct a K9oClient bound to the supplied options.
38
38
  #
39
- # Per ch13 §2.1.8 spec sample:
39
+ # Per spec sample:
40
40
  # k9o = K9o.create_client(
41
41
  # api_key: ENV["K9O_API_KEY"],
42
42
  # org_slug: "acme",
data/lib/k9o/compute.rb CHANGED
@@ -4,7 +4,7 @@ module K9o
4
4
  # Compute namespace (Compute LLMs registry).
5
5
  # k9o.compute.llms.*
6
6
  class Compute
7
- # Curated 9-model closed enum per ch07 §10.1 (extensible v2.x).
7
+ # Curated 9-model closed enum (extensible v2.x).
8
8
  LLM_MODEL_IDS = %w[
9
9
  mistral-7b mistral-8x7b llama-3-8b llama-3-70b
10
10
  claude-3-5-sonnet gpt-4o gpt-4o-mini
@@ -17,7 +17,7 @@ module K9o
17
17
  @llms = Llms.new(config)
18
18
  end
19
19
 
20
- # k9o.compute.llms.* per ch07 §10.
20
+ # k9o.compute.llms.*.
21
21
  class Llms
22
22
  def initialize(config)
23
23
  @config = config
@@ -36,7 +36,7 @@ module K9o
36
36
  path: UrlGrammar.project_path(slug, "compute/llms/#{enc(model_id)}"))
37
37
  end
38
38
 
39
- # Synchronous inference per ch07 §10.2 (PROJECT_AUTHOR/ADMIN).
39
+ # Synchronous inference (PROJECT_AUTHOR/ADMIN).
40
40
  def invoke(model_id, prompt:, params: nil)
41
41
  slug = Studio.require_project_slug(@config, 'compute.llms')
42
42
  body = { 'prompt' => prompt }
@@ -45,8 +45,8 @@ module K9o
45
45
  path: UrlGrammar.project_path(slug, "compute/llms/#{enc(model_id)}/invoke"), body: body)
46
46
  end
47
47
 
48
- # Streaming inference (SSE per-token) per ch07 §10.2. Returns an
49
- # Enumerator of chunk hashes (ch13 §8 Ruby idiom). Consume with
48
+ # Streaming inference (SSE per-token). Returns an
49
+ # Enumerator of chunk hashes (Ruby idiom). Consume with
50
50
  # `.each { |chunk| ... }`.
51
51
  def invoke_stream(model_id, prompt:, params: nil)
52
52
  slug = Studio.require_project_slug(@config, 'compute.llms')
data/lib/k9o/data.rb CHANGED
@@ -132,7 +132,7 @@ module K9o
132
132
  id_filter = @filters.find { |col, op, _| col == 'id' && op == 'eq' }
133
133
  raise KError.new(
134
134
  code: 'K9O_INVALID_FIELD_VALUE',
135
- message: 'update() requires .eq("id", ...) filter; row-mass update is not supported at v0.1.0',
135
+ message: 'update() requires .eq("id", ...) filter; changing many rows in one call is not supported',
136
136
  context: { collection: @collection }
137
137
  ) unless id_filter
138
138
 
@@ -146,7 +146,7 @@ module K9o
146
146
  id_filter = @filters.find { |col, op, _| col == 'id' && op == 'eq' }
147
147
  raise KError.new(
148
148
  code: 'K9O_INVALID_FIELD_VALUE',
149
- message: 'delete() requires .eq("id", ...) filter; row-mass delete is not supported at v0.1.0',
149
+ message: 'delete() requires .eq("id", ...) filter; deleting many rows in one call is not supported',
150
150
  context: { collection: @collection }
151
151
  ) unless id_filter
152
152
 
data/lib/k9o/envelope.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module K9o
4
- # Standard ch01 §1.1 envelope returned by every k9o surface on success.
4
+ # Standard envelope returned by every k9o surface on success.
5
5
  class Envelope
6
6
  attr_reader :data, :meta
7
7
 
@@ -18,7 +18,7 @@ module K9o
18
18
  end
19
19
  end
20
20
 
21
- # Meta accessor sugar per ch13 §5.
21
+ # Meta accessor sugar.
22
22
  class Meta
23
23
  attr_reader :cursor, :subscription, :idempotency, :warnings, :cost, :timing, :context
24
24
 
@@ -6,7 +6,7 @@ require 'uri'
6
6
  require_relative 'multipart'
7
7
 
8
8
  module K9o
9
- # Retry + backoff policy (ch13 §7.1). Applied to idempotent methods
9
+ # Retry + backoff policy. Applied to idempotent methods
10
10
  # (GET/HEAD/OPTIONS/DELETE) on transient failures only (transport error /
11
11
  # 502 / 503 / 504 / 429); semantic 4xx and non-idempotent methods are
12
12
  # never retried.
@@ -55,7 +55,7 @@ module K9o
55
55
  module_function
56
56
 
57
57
  # Issue a request with retry on transient failures. Idempotent methods
58
- # are retried with backoff per config.retry_config (ch13 §7.1);
58
+ # are retried with backoff per config.retry_config;
59
59
  # semantic / non-idempotent failures raise immediately.
60
60
  #
61
61
  # `headers:` carries per-call header overrides on top of
@@ -210,12 +210,12 @@ module K9o
210
210
  end
211
211
 
212
212
  # Open an SSE stream and return an Enumerator yielding decoded `data:`
213
- # payloads (parsed JSON). Used by Compute LLMs #invoke_stream (ch07
214
- # §10.2) + Realtime #subscribe SSE transport (ch07 §11.3). The [DONE]
213
+ # payloads (parsed JSON). Used by Compute LLMs #invoke_stream
214
+ # and the Realtime #subscribe SSE transport. The [DONE]
215
215
  # sentinel terminates the stream; non-2xx raises KError before any
216
216
  # event is yielded.
217
217
  #
218
- # Per ch13 §8 the Ruby async-iteration idiom is Enumerator — caller
218
+ # Per the Ruby async-iteration idiom is Enumerator — caller
219
219
  # writes `client.compute.llms.invoke_stream(...).each { |chunk| ... }`.
220
220
  def stream_sse(config:, method:, path:, body: nil, query: nil)
221
221
  url = "#{Region.resolve_origin(config).sub(%r{/\z}, '')}#{path}"
@@ -3,7 +3,7 @@
3
3
  module K9o
4
4
  # Migration lifecycle namespace — k9o.migrations.*.
5
5
  #
6
- # TYPE MODEL (ch13 §2.2, cemented f21b3c15 — Ruby is TIER-3):
6
+ # TYPE MODEL (, cemented f21b3c15 — Ruby is TIER-3):
7
7
  #
8
8
  # Ruby keeps a RUNTIME HASH PASS-THROUGH for migration payloads (the
9
9
  # gateway is the fail-closed source of truth; SDK types are ergonomics +
@@ -104,7 +104,7 @@ module K9o
104
104
  path: UrlGrammar.project_path(slug, "migrations/#{enc(version)}"))
105
105
  end
106
106
 
107
- # Queue migrations for maker-checker approval per ch06 §8.
107
+ # Queue migrations for maker-checker approval.
108
108
  def queue(migrations)
109
109
  slug = require_project_slug
110
110
  HttpTransport.request(config: @config, method: 'POST',
data/lib/k9o/org.rb CHANGED
@@ -4,7 +4,7 @@ module K9o
4
4
  # Org-plane bound namespace — k9o.org.*. Singular
5
5
  # bound-org namespace (distinct from k9o.orgs collection): members /
6
6
  # groups / smtp / audit_log / gate (roles + idp_providers) + default_llm.
7
- # Org-plane URL grammar per v2.5.68 §5.4 routes against the org subdomain
7
+ # Org-plane URL grammar routes against the org subdomain
8
8
  # without the @<projectSlug>/ prefix.
9
9
  class Org
10
10
  attr_reader :members, :groups, :smtp, :audit_log, :gate, :default_llm
@@ -192,7 +192,7 @@ module K9o
192
192
  end
193
193
  end
194
194
 
195
- # k9o.org.default_llm.* per ch07 §10.3 (ORG_ADMIN; tier-gated).
195
+ # k9o.org.default_llm.* (ORG_ADMIN; tier-gated).
196
196
  class DefaultLlm
197
197
  def initialize(config)
198
198
  @config = config
@@ -203,7 +203,7 @@ module K9o
203
203
  HttpTransport.request(config: @config, method: 'GET', path: UrlGrammar.org_path('org/default-llm'))
204
204
  end
205
205
 
206
- # Set the org-default LLM (ORG_ADMIN; tier-gated per §10.1).
206
+ # Set the org-default LLM (ORG_ADMIN; tier-gated).
207
207
  def set(model_id)
208
208
  HttpTransport.request(config: @config, method: 'PATCH',
209
209
  path: UrlGrammar.org_path('org/default-llm'), body: { 'modelId' => model_id })
data/lib/k9o/realtime.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  module K9o
4
4
  # Realtime Subscriptions namespace (ALL-LIVE primitive).
5
5
  #
6
- # Ruby idiom per ch13 §8: #subscribe returns an Enumerator iterated via
7
- # `.each`. Per ch07 §11.3 + the SDK-abstracted-primitive discipline the
6
+ # Ruby idiom: #subscribe returns an Enumerator iterated via
7
+ # `.each`. Per + the SDK-abstracted-primitive discipline the
8
8
  # SDK picks the transport; SPLIT (polling) is the internal fallback. The
9
9
  # Net::HTTP-based Ruby SDK uses SSE primary (no stdlib WebSocket);
10
10
  # #subscribe_poll exposes the poll fallback. #replay is one-shot catch-up.
@@ -13,7 +13,7 @@ module K9o
13
13
  @config = config
14
14
  end
15
15
 
16
- # Subscribe via SSE transport (primary per §11.3); returns an
16
+ # Subscribe via SSE transport (primary); returns an
17
17
  # Enumerator yielding event hashes.
18
18
  def subscribe(topic, filter: nil)
19
19
  slug = Studio.require_project_slug(@config, 'realtime')
@@ -23,7 +23,7 @@ module K9o
23
23
  path: UrlGrammar.project_path(slug, 'realtime/subscribe'), query: q)
24
24
  end
25
25
 
26
- # One-shot historical replay per ch07 §11.2 (capped 10k server-side).
26
+ # One-shot historical replay (capped 10k server-side).
27
27
  def replay(topic, from_sequence:, filter: nil, until_sequence: nil, limit: nil)
28
28
  slug = Studio.require_project_slug(@config, 'realtime')
29
29
  unless from_sequence.is_a?(Integer) && from_sequence >= 0
@@ -42,13 +42,13 @@ module K9o
42
42
  path: UrlGrammar.project_path(slug, 'realtime/replay'), body: body)
43
43
  end
44
44
 
45
- # Poll-transport fallback per §11.3 (SDK-internal SPLIT). Single batch
45
+ # Poll-transport fallback (SDK-internal SPLIT). Single batch
46
46
  # via replay endpoint; caller loops tracking highest observed sequence.
47
47
  def subscribe_poll(topic, from_sequence:, filter: nil)
48
48
  replay(topic, from_sequence: from_sequence, filter: filter)
49
49
  end
50
50
 
51
- # Typed builders for the 6 closed topic families per ch07 §11.1.
51
+ # Typed builders for the 6 closed topic families.
52
52
  module Topic
53
53
  module_function
54
54
 
data/lib/k9o/storage.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require 'cgi'
4
4
 
5
5
  module K9o
6
- # `client.storage` buckets and objects (ch04 §9), against
6
+ # `client.storage` buckets and objects, against
7
7
  # `/@<project_slug>/storage/buckets...`.
8
8
  #
9
9
  # k9o.storage.create_bucket('avatars', public: false)
data/lib/k9o/studio.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  module K9o
4
4
  # Studio namespace (workflows + dashboards).
5
- # Ruby idiom per ch13 §2.1.8: snake_case + raise K9o::KError + Envelope return.
5
+ # Ruby idiom: snake_case + raise K9o::KError + Envelope return.
6
6
  #
7
7
  # k9o.studio.workflows.list(status: 'active')
8
8
  # k9o.studio.dashboards.pin('dsh_x')
@@ -25,7 +25,7 @@ module K9o
25
25
  slug
26
26
  end
27
27
 
28
- # k9o.studio.workflows.* per ch07 §9.
28
+ # k9o.studio.workflows.*.
29
29
  class Workflows
30
30
  attr_reader :runs
31
31
 
@@ -69,7 +69,7 @@ module K9o
69
69
  path: UrlGrammar.project_path(slug, "workflows/#{encode(workflow_id)}"))
70
70
  end
71
71
 
72
- # Manual-trigger a run (trigger_type=manual only) per ch07 §9.6.
72
+ # Manual-trigger a run (trigger_type=manual only).
73
73
  def trigger(workflow_id, trigger_context = {})
74
74
  slug = Studio.require_project_slug(@config, 'studio.workflows')
75
75
  HttpTransport.request(config: @config, method: 'POST',
@@ -83,7 +83,7 @@ module K9o
83
83
  ::URI.encode_www_form_component(s)
84
84
  end
85
85
 
86
- # k9o.studio.workflows.runs.* per ch07 §9.6.
86
+ # k9o.studio.workflows.runs.*.
87
87
  class Runs
88
88
  def initialize(config)
89
89
  @config = config
@@ -116,7 +116,7 @@ module K9o
116
116
  end
117
117
  end
118
118
 
119
- # k9o.studio.dashboards.* per ch04 §3.10.
119
+ # k9o.studio.dashboards.*.
120
120
  class Dashboards
121
121
  def initialize(config)
122
122
  @config = config
@@ -3,7 +3,7 @@
3
3
  require 'uri'
4
4
 
5
5
  module K9o
6
- # URL grammar v2.5.68 helpers.
6
+ # URL grammar helpers.
7
7
  module UrlGrammar
8
8
  SLUG_RE = /\A[a-z][a-z0-9-]{1,62}\z/
9
9
 
@@ -69,7 +69,7 @@ module K9o
69
69
  # OPTIONAL — it defaults to the platform apex https://api.k9o.io. When the
70
70
  # (validated) host is a bare apex in ORG_DERIVABLE_APEXES and org_slug is
71
71
  # supplied, the SDK composes the canonical org-subdomain wire root
72
- # https://<org_slug>.<apex> (ch01 §5.4). An explicit <org_slug> subdomain,
72
+ # https://<org_slug>.<apex>. An explicit <org_slug> subdomain,
73
73
  # a self-hosted / Sovereign host, or a dev host (anything not in that
74
74
  # set) passes through unchanged — org_slug is intentionally NOT composed
75
75
  # onto a non-apex host.
data/lib/k9o/vault.rb CHANGED
@@ -4,7 +4,7 @@ require 'base64'
4
4
  require 'uri'
5
5
 
6
6
  module K9o
7
- # `k9o.kibo.vault.secrets.*` — the §14 typed secrets surface
7
+ # `k9o.kibo.vault.secrets.*` — the typed secrets surface
8
8
  # (`services/gateway/src/routes/vault-secrets.ts`). Full family: list / get /
9
9
  # create / reveal_challenge / reveal / update / rotate / move / delete.
10
10
  #
@@ -206,8 +206,8 @@ module K9o
206
206
  end
207
207
 
208
208
  # `k9o.kibo.vault.*` — the Kibo vault surface (member-plane, project-scoped).
209
- # Currently just `secrets` (ch08 §14); a `zk_deks` accessor
210
- # (ch08 §11.3.2 F.5, `POST vault/zk-deks` / `GET vault/zk-deks/<id>`) would
209
+ # Currently just `secrets`; a `zk_deks` accessor
210
+ # (F.5, `POST vault/zk-deks` / `GET vault/zk-deks/<id>`) would
211
211
  # nest here alongside it if/when that surface is built for Ruby — out of
212
212
  # scope for this wrapper, which only covers the vault-secrets audit gap.
213
213
  class KiboVault
@@ -220,7 +220,7 @@ module K9o
220
220
 
221
221
  # `k9o.kibo.*` — per-client namespace root for the Kibo vault REST surface.
222
222
  # Distinct from the module-level `K9o::Kibo` (native ZK `encrypt`/`decrypt`
223
- # FFI bindings, ch08 §11.3.1/§11.3.3.6, called directly as
223
+ # FFI bindings, /, called directly as
224
224
  # `K9o::Kibo.encrypt`/`.decrypt` since that surface needs no per-client HTTP
225
225
  # config): this class exists so `client.kibo.vault.secrets.*` is reachable
226
226
  # per client instance, mirroring the TS reference's
data/lib/k9o/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module K9o
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.1'
5
5
  end
data/lib/k9o.rb CHANGED
@@ -46,7 +46,7 @@ require_relative 'k9o/org'
46
46
  # kibo ZK BYOK/HYOK crypto — self-guards its native binding (LoadError-safe), so
47
47
  # requiring k9o never breaks on a platform without the kibo native lib.
48
48
  require_relative 'k9o/kibo'
49
- # kibo vault REST surface (client.kibo.vault.secrets) — ch08 §14.
49
+ # kibo vault REST surface (client.kibo.vault.secrets) —.
50
50
  require_relative 'k9o/vault'
51
51
  # Barbican guardrail SDK — self-guards its native binding (LoadError-safe), so
52
52
  # requiring k9o never breaks on a platform without the barbican native lib.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: k9o
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kilimanjaro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-23 00:00:00.000000000 Z
11
+ date: 2026-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -74,6 +74,7 @@ licenses:
74
74
  - Apache-2.0
75
75
  metadata:
76
76
  homepage_uri: https://kilimanjaro.dev
77
+ documentation_uri: https://docs.kilimanjaro.dev
77
78
  source_code_uri: https://github.com/k9o-dev/sdk-ruby
78
79
  changelog_uri: https://github.com/k9o-dev/sdk-ruby/blob/main/CHANGELOG.md
79
80
  post_install_message: