k9o 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +10 -0
- data/LICENSE +201 -0
- data/NOTICE +4 -0
- data/README.md +546 -0
- data/k9o.gemspec +41 -0
- data/lib/k9o/ai.rb +28 -0
- data/lib/k9o/audit.rb +29 -0
- data/lib/k9o/barbican.rb +239 -0
- data/lib/k9o/client.rb +59 -0
- data/lib/k9o/compute.rb +67 -0
- data/lib/k9o/data.rb +157 -0
- data/lib/k9o/envelope.rb +64 -0
- data/lib/k9o/functions.rb +51 -0
- data/lib/k9o/gate.rb +64 -0
- data/lib/k9o/http_transport.rb +318 -0
- data/lib/k9o/kerror.rb +52 -0
- data/lib/k9o/kibo.rb +114 -0
- data/lib/k9o/me.rb +160 -0
- data/lib/k9o/migrations.rb +244 -0
- data/lib/k9o/multipart.rb +42 -0
- data/lib/k9o/org.rb +213 -0
- data/lib/k9o/orgs.rb +33 -0
- data/lib/k9o/policies.rb +65 -0
- data/lib/k9o/projects.rb +33 -0
- data/lib/k9o/realtime.rb +80 -0
- data/lib/k9o/region.rb +95 -0
- data/lib/k9o/storage.rb +176 -0
- data/lib/k9o/studio.rb +175 -0
- data/lib/k9o/url_grammar.rb +113 -0
- data/lib/k9o/vault.rb +235 -0
- data/lib/k9o/version.rb +5 -0
- data/lib/k9o.rb +54 -0
- data/sig/k9o/ai.rbs +16 -0
- data/sig/k9o/gate.rbs +11 -0
- data/sig/k9o/migrations.rbs +138 -0
- data/sig/k9o/region.rbs +19 -0
- data/sig/k9o/storage.rbs +41 -0
- metadata +98 -0
data/README.md
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
# k9o
|
|
2
|
+
|
|
3
|
+
The Kilimanjaro platform SDK for Ruby.
|
|
4
|
+
|
|
5
|
+
Documentation: https://kilimanjaro.dev. Platform API: https://api.k9o.io.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Install](#install)
|
|
10
|
+
- [Quick start](#quick-start)
|
|
11
|
+
- [Authentication and project context](#authentication-and-project-context)
|
|
12
|
+
- [Running queries](#running-queries)
|
|
13
|
+
- [Handling errors](#handling-errors)
|
|
14
|
+
- [Appendix](#appendix)
|
|
15
|
+
- [License](#license)
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
gem install k9o
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or add it to your `Gemfile`:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
gem "k9o"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Requires Ruby 3.2 or newer. See [requirements](#requirements) for details.
|
|
30
|
+
|
|
31
|
+
## Quick start
|
|
32
|
+
|
|
33
|
+
The examples use a `tasks` collection with `title` and `done` fields.
|
|
34
|
+
|
|
35
|
+
### Create the client
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
require "k9o"
|
|
39
|
+
|
|
40
|
+
k9o = K9o.create_client(
|
|
41
|
+
org_slug: "acme",
|
|
42
|
+
project_slug: "task-app",
|
|
43
|
+
api_key: ENV.fetch("K9O_API_KEY")
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Add a task
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
new_task = { "title" => "Write the README", "done" => false }
|
|
51
|
+
created = k9o.from("tasks").insert(new_task)
|
|
52
|
+
puts "created: #{created.data['title']}"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
created: Write the README
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### List tasks
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
response = k9o.from("tasks").select.eq("done", false).limit(10).execute
|
|
63
|
+
response.data.each do |task|
|
|
64
|
+
puts "#{task['title']} #{task['done']}"
|
|
65
|
+
end
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
Write the README false
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Update and delete a task
|
|
73
|
+
|
|
74
|
+
Both calls need an `eq("id", ...)` filter.
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
task_id = created.data["id"]
|
|
78
|
+
|
|
79
|
+
patch = { "done" => true }
|
|
80
|
+
k9o.from("tasks").update(patch).eq("id", task_id).execute
|
|
81
|
+
|
|
82
|
+
k9o.from("tasks").delete.eq("id", task_id).execute
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Authentication and project context
|
|
86
|
+
|
|
87
|
+
The client needs a key and, for project calls, an org and project.
|
|
88
|
+
|
|
89
|
+
| Option | What it does |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `api_key:` | Bearer token sent with every request. |
|
|
92
|
+
| `org_slug:` | Organization. On the default host the SDK uses `https://<org_slug>.api.k9o.io`. |
|
|
93
|
+
| `project_slug:` | Project. Required by every project-scoped namespace. |
|
|
94
|
+
|
|
95
|
+
See [client options](#client-options) for every option.
|
|
96
|
+
|
|
97
|
+
### Choose a host
|
|
98
|
+
|
|
99
|
+
Pick one of two forms.
|
|
100
|
+
|
|
101
|
+
- Default platform host: pass the org slug, project slug and key.
|
|
102
|
+
- Custom or self-hosted host: pass `base_url`, project slug and key, and no org slug.
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
k9o = K9o.create_client(
|
|
106
|
+
base_url: "https://k9o.internal.example.com",
|
|
107
|
+
project_slug: "task-app",
|
|
108
|
+
api_key: ENV.fetch("K9O_API_KEY")
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The base URL rules are listed under [regional hosts](#regional-hosts).
|
|
113
|
+
|
|
114
|
+
## Running queries
|
|
115
|
+
|
|
116
|
+
Chain filters on `select`, then call `execute`. The result carries rows in `data` and details in `meta`.
|
|
117
|
+
|
|
118
|
+
| Call | What it does |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `eq(column, value)` | Keep rows where the column equals the value. |
|
|
121
|
+
| `limit(n)` | Return at most `n` rows. |
|
|
122
|
+
| `cursor(token)` | Continue from `meta.cursor.next`. |
|
|
123
|
+
|
|
124
|
+
See [filters](#filters) and [paging](#paging) for all calls, and [response metadata](#response-metadata) for every `meta` field.
|
|
125
|
+
|
|
126
|
+
A sub-object the server did not send is `nil`, so use `&.` when it may be absent.
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
request_id = response.meta.context.request_id
|
|
130
|
+
total = response.meta.cursor.total_count
|
|
131
|
+
puts "#{request_id} #{total}"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
req_01H... 1
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Handling errors
|
|
139
|
+
|
|
140
|
+
Failures raise `K9o::KError`, a subclass of `StandardError`. Branch on `code`.
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
begin
|
|
144
|
+
k9o.from("missing").select.execute
|
|
145
|
+
rescue K9o::KError => error
|
|
146
|
+
puts "#{error.code} #{error.status} #{error.request_id}"
|
|
147
|
+
puts error.message
|
|
148
|
+
end
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
K9O_NOT_FOUND 404 req_01H...
|
|
153
|
+
Collection not found
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- See [error attributes](#error-attributes) for every field.
|
|
157
|
+
- See [error codes](#error-codes) for the codes the SDK raises.
|
|
158
|
+
- See [retries](#retries) for automatic retry rules.
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
## Appendix
|
|
162
|
+
|
|
163
|
+
### Requirements
|
|
164
|
+
|
|
165
|
+
| Requirement | Version |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `Ruby` | 3.2 or newer |
|
|
168
|
+
| `Runtime gems` | None (uses `Net::HTTP`, `json` and `uri` from the standard library) |
|
|
169
|
+
|
|
170
|
+
### Client options
|
|
171
|
+
|
|
172
|
+
| Option | What it does |
|
|
173
|
+
|---|---|
|
|
174
|
+
| `api_key:` | Bearer token sent with every request. |
|
|
175
|
+
| `org_slug:` | Organization. On the default host the SDK uses `https://<org_slug>.api.k9o.io`. |
|
|
176
|
+
| `project_slug:` | Project. Required by every project-scoped namespace. |
|
|
177
|
+
| `base_url:` | Scheme and host only. Defaults to `https://api.k9o.io`. |
|
|
178
|
+
| `default_headers:` | Extra headers added to every request. |
|
|
179
|
+
| `http_client:` | A `Net::HTTP`-compatible object used instead of the default connection. |
|
|
180
|
+
|
|
181
|
+
`org_slug` and `project_slug` are also sent as the `x-k9o-org-slug` and `x-k9o-project-slug` headers.
|
|
182
|
+
|
|
183
|
+
### Methods by namespace
|
|
184
|
+
|
|
185
|
+
Every method is called on the client, for example `k9o.projects.list`. Return values are `Envelope` objects.
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
#### Data
|
|
190
|
+
|
|
191
|
+
`k9o.from(collection)` reads and writes rows in one collection of the active project.
|
|
192
|
+
|
|
193
|
+
| Method | What it does |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `select` | Start a query. Finish with `execute`. |
|
|
196
|
+
| `insert(record)` | Add one row and return it. |
|
|
197
|
+
| `update(patch)` | Change one row. Needs `eq("id", ...)`. |
|
|
198
|
+
| `delete` | Remove one row. Needs `eq("id", ...)`. |
|
|
199
|
+
|
|
200
|
+
##### Filters
|
|
201
|
+
|
|
202
|
+
Chain filters before `execute`. Values are matched against one column.
|
|
203
|
+
|
|
204
|
+
| Method | What it does |
|
|
205
|
+
|---|---|
|
|
206
|
+
| `eq(column, value)` | Equal to value. |
|
|
207
|
+
| `neq(column, value)` | Not equal to value. |
|
|
208
|
+
| `gt(column, value)` | Greater than value. |
|
|
209
|
+
| `gte(column, value)` | Greater than or equal. |
|
|
210
|
+
| `lt(column, value)` | Less than value. |
|
|
211
|
+
| `lte(column, value)` | Less than or equal. |
|
|
212
|
+
| `in_(column, values)` | Equal to any value in the list. |
|
|
213
|
+
| `not_in(column, values)` | Equal to none of the values. |
|
|
214
|
+
| `like(column, pattern)` | Case-sensitive pattern match. |
|
|
215
|
+
| `ilike(column, pattern)` | Case-insensitive pattern match. |
|
|
216
|
+
| `is(column, value)` | Match `null`, `true` or `false`. |
|
|
217
|
+
| `filter(column, op, value)` | Generic form with an explicit operator name. |
|
|
218
|
+
|
|
219
|
+
##### Paging
|
|
220
|
+
|
|
221
|
+
| Method | What it does |
|
|
222
|
+
|---|---|
|
|
223
|
+
| `limit(n)` | Maximum rows to return. |
|
|
224
|
+
| `cursor(token)` | Continue from `meta.cursor.next`. |
|
|
225
|
+
| `count(mode)` | Row count mode: `none`, `exact` or `estimated`. |
|
|
226
|
+
|
|
227
|
+
#### Projects
|
|
228
|
+
|
|
229
|
+
`k9o.projects` manages projects in the active organization.
|
|
230
|
+
|
|
231
|
+
| Method | What it does |
|
|
232
|
+
|---|---|
|
|
233
|
+
| `k9o.projects.list` | List projects you can access. |
|
|
234
|
+
| `k9o.projects.create` | Create a project from `slug` and `name`. |
|
|
235
|
+
| `k9o.projects.get` | Read a project by slug. |
|
|
236
|
+
| `k9o.projects.update` | Change a project's `name`. |
|
|
237
|
+
|
|
238
|
+
#### Gate (end-user sign-in)
|
|
239
|
+
|
|
240
|
+
`k9o.gate` signs in the active project's end users and needs `project_slug`.
|
|
241
|
+
|
|
242
|
+
| Method | What it does |
|
|
243
|
+
|---|---|
|
|
244
|
+
| `k9o.gate.sign_up` | Create an end user from email and password. |
|
|
245
|
+
| `k9o.gate.sign_in` | Sign in with email and password. |
|
|
246
|
+
| `k9o.gate.sign_out` | Revoke the session's refresh token. |
|
|
247
|
+
| `k9o.gate.whoami` | Return the signed-in identity. |
|
|
248
|
+
| `k9o.gate.refresh_token` | Exchange a refresh token for a new access token. |
|
|
249
|
+
| `k9o.gate.verify_session` | Check that the current session is valid. |
|
|
250
|
+
| `k9o.gate.hosted` | Return the hosted sign-in `signInUrl` and `rpId`. |
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
session = k9o.gate.sign_in(email: "ada@example.com", password: "correct-horse")
|
|
254
|
+
user = session.data["user"]
|
|
255
|
+
puts user["email"]
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
```text
|
|
259
|
+
ada@example.com
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Storage
|
|
263
|
+
|
|
264
|
+
`k9o.storage` manages buckets and the objects inside them.
|
|
265
|
+
|
|
266
|
+
##### Buckets
|
|
267
|
+
|
|
268
|
+
| Method | What it does |
|
|
269
|
+
|---|---|
|
|
270
|
+
| `k9o.storage.create_bucket` | Create a bucket by name. |
|
|
271
|
+
| `k9o.storage.get_bucket` | Read one bucket. |
|
|
272
|
+
| `k9o.storage.list_buckets` | List buckets. |
|
|
273
|
+
| `k9o.storage.update_bucket` | Change bucket settings. |
|
|
274
|
+
| `k9o.storage.delete_bucket` | Delete a bucket. Pass `empty` to purge its objects first. |
|
|
275
|
+
|
|
276
|
+
##### Objects
|
|
277
|
+
|
|
278
|
+
`k9o.storage.from(bucket)` returns a handle for one bucket.
|
|
279
|
+
|
|
280
|
+
| Method | What it does |
|
|
281
|
+
|---|---|
|
|
282
|
+
| `k9o.storage.from(bucket).upload` | Store bytes at a path. Existing paths are kept unless `upsert` is true. |
|
|
283
|
+
| `k9o.storage.from(bucket).create_signed_url` | Create a time-limited download link. |
|
|
284
|
+
| `k9o.storage.from(bucket).list` | List objects, optionally under a `prefix`. |
|
|
285
|
+
| `k9o.storage.from(bucket).remove` | Delete the object at a path. |
|
|
286
|
+
|
|
287
|
+
`expires_in` is required, in seconds from 1 to 604800.
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
avatars = k9o.storage.from("avatars")
|
|
291
|
+
avatars.upload("ada.png", "...image bytes...", content_type: "image/png")
|
|
292
|
+
signed = avatars.create_signed_url("ada.png", expires_in: 300)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### Functions
|
|
296
|
+
|
|
297
|
+
`k9o.functions` deploys and runs server-side functions.
|
|
298
|
+
|
|
299
|
+
| Method | What it does |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `k9o.functions.deploy` | Deploy a function from `name`, `runtime` and `code`. |
|
|
302
|
+
| `k9o.functions.list` | List functions. |
|
|
303
|
+
| `k9o.functions.get` | Read one function by name. |
|
|
304
|
+
| `k9o.functions.delete` | Remove a function. |
|
|
305
|
+
| `k9o.functions.invoke` | Run a function with a payload. |
|
|
306
|
+
|
|
307
|
+
#### Migrations
|
|
308
|
+
|
|
309
|
+
`k9o.migrations` changes the project's schema.
|
|
310
|
+
|
|
311
|
+
| Method | What it does |
|
|
312
|
+
|---|---|
|
|
313
|
+
| `k9o.migrations.apply` | Apply migrations now. |
|
|
314
|
+
| `k9o.migrations.list` | List applied migrations. |
|
|
315
|
+
| `k9o.migrations.get` | Read one migration by version. |
|
|
316
|
+
| `k9o.migrations.queue` | Queue migrations for approval. |
|
|
317
|
+
| `k9o.migrations.list_pending` | List queued migrations. |
|
|
318
|
+
| `k9o.migrations.apply_pending` | Apply one queued migration. |
|
|
319
|
+
| `k9o.migrations.reject_pending` | Reject one queued migration. |
|
|
320
|
+
| `k9o.migrations.delete_pending` | Delete one queued migration. |
|
|
321
|
+
|
|
322
|
+
#### Policies
|
|
323
|
+
|
|
324
|
+
`k9o.policies` manages access policy bundles.
|
|
325
|
+
|
|
326
|
+
| Method | What it does |
|
|
327
|
+
|---|---|
|
|
328
|
+
| `k9o.policies.current` | Read the published bundle. |
|
|
329
|
+
| `k9o.policies.list` | List bundles. |
|
|
330
|
+
| `k9o.policies.create` | Create a bundle from `name` and `rules`. |
|
|
331
|
+
| `k9o.policies.validate` | Check rules without saving. |
|
|
332
|
+
| `k9o.policies.get` | Read one bundle. |
|
|
333
|
+
| `k9o.policies.update` | Change a bundle. |
|
|
334
|
+
| `k9o.policies.delete` | Remove a bundle. |
|
|
335
|
+
| `k9o.policies.publish` | Make a bundle current. |
|
|
336
|
+
|
|
337
|
+
#### Audit
|
|
338
|
+
|
|
339
|
+
`k9o.audit` reads the project's audit events.
|
|
340
|
+
|
|
341
|
+
| Method | What it does |
|
|
342
|
+
|---|---|
|
|
343
|
+
| `k9o.audit.query` | Search events by time range, type and more. |
|
|
344
|
+
|
|
345
|
+
#### AI embeddings
|
|
346
|
+
|
|
347
|
+
`k9o.ai` creates text embeddings.
|
|
348
|
+
|
|
349
|
+
| Method | What it does |
|
|
350
|
+
|---|---|
|
|
351
|
+
| `k9o.ai.embed(input:, model: nil)` | Embed one string or a list of strings. |
|
|
352
|
+
|
|
353
|
+
#### Language models
|
|
354
|
+
|
|
355
|
+
`k9o.compute.llms` lists and calls hosted models.
|
|
356
|
+
|
|
357
|
+
| Method | What it does |
|
|
358
|
+
|---|---|
|
|
359
|
+
| `k9o.compute.llms.list` | List available models. |
|
|
360
|
+
| `k9o.compute.llms.read` | Read one model. |
|
|
361
|
+
| `k9o.compute.llms.invoke` | Send a prompt and get the reply. |
|
|
362
|
+
| `k9o.compute.llms.invoke_stream` | Stream the reply token by token (returns an `Enumerator`). |
|
|
363
|
+
|
|
364
|
+
#### Realtime
|
|
365
|
+
|
|
366
|
+
`k9o.realtime` delivers live events for a topic.
|
|
367
|
+
|
|
368
|
+
| Method | What it does |
|
|
369
|
+
|---|---|
|
|
370
|
+
| `k9o.realtime.subscribe` | Stream live events (returns an `Enumerator`). |
|
|
371
|
+
| `k9o.realtime.replay` | Read past events from a sequence number. |
|
|
372
|
+
| `k9o.realtime.subscribe_poll` | Poll for events from a sequence number. |
|
|
373
|
+
|
|
374
|
+
`K9o::Realtime::Topic` builds topic names, for example `Topic.collection("tasks")`.
|
|
375
|
+
|
|
376
|
+
#### Studio
|
|
377
|
+
|
|
378
|
+
`k9o.studio` manages workflows and dashboards.
|
|
379
|
+
|
|
380
|
+
##### Workflows
|
|
381
|
+
|
|
382
|
+
| Method | What it does |
|
|
383
|
+
|---|---|
|
|
384
|
+
| `k9o.studio.workflows.list` | List workflows. |
|
|
385
|
+
| `k9o.studio.workflows.create` | Create a workflow. |
|
|
386
|
+
| `k9o.studio.workflows.read` | Read one workflow. |
|
|
387
|
+
| `k9o.studio.workflows.update` | Change a workflow. |
|
|
388
|
+
| `k9o.studio.workflows.delete` | Delete a workflow. |
|
|
389
|
+
| `k9o.studio.workflows.trigger` | Start a run. |
|
|
390
|
+
| `k9o.studio.workflows.runs.list` | List a workflow's runs. |
|
|
391
|
+
| `k9o.studio.workflows.runs.read` | Read one run. |
|
|
392
|
+
| `k9o.studio.workflows.runs.cancel` | Cancel a run. |
|
|
393
|
+
|
|
394
|
+
##### Dashboards
|
|
395
|
+
|
|
396
|
+
| Method | What it does |
|
|
397
|
+
|---|---|
|
|
398
|
+
| `k9o.studio.dashboards.list` | List dashboards. |
|
|
399
|
+
| `k9o.studio.dashboards.create` | Create a dashboard. |
|
|
400
|
+
| `k9o.studio.dashboards.read` | Read one dashboard. |
|
|
401
|
+
| `k9o.studio.dashboards.update` | Change a dashboard. |
|
|
402
|
+
| `k9o.studio.dashboards.delete` | Delete a dashboard. |
|
|
403
|
+
| `k9o.studio.dashboards.pin` | Pin to the workspace. |
|
|
404
|
+
| `k9o.studio.dashboards.unpin` | Remove from the workspace. |
|
|
405
|
+
|
|
406
|
+
#### Current user
|
|
407
|
+
|
|
408
|
+
`k9o.me` covers the signed-in account.
|
|
409
|
+
|
|
410
|
+
| Method | What it does |
|
|
411
|
+
|---|---|
|
|
412
|
+
| `k9o.me.profile.get` | Read the profile. |
|
|
413
|
+
| `k9o.me.profile.update` | Change the display name. |
|
|
414
|
+
| `k9o.me.sessions.list` | List active sessions. |
|
|
415
|
+
| `k9o.me.sessions.revoke` | End one session. |
|
|
416
|
+
| `k9o.me.sessions.revoke_all` | End all sessions. |
|
|
417
|
+
| `k9o.me.api_tokens.list` | List API tokens. |
|
|
418
|
+
| `k9o.me.api_tokens.create` | Create an API token. |
|
|
419
|
+
| `k9o.me.api_tokens.delete` | Delete an API token. |
|
|
420
|
+
| `k9o.me.notifications.list` | List notifications. |
|
|
421
|
+
| `k9o.me.notifications.mark_read` | Mark one as read. |
|
|
422
|
+
| `k9o.me.notifications.mark_all_read` | Mark all as read. |
|
|
423
|
+
| `k9o.me.audit_log.query` | Search your own audit events. |
|
|
424
|
+
| `k9o.me.data_export.request` | Request a data export. |
|
|
425
|
+
| `k9o.me.data_export.status` | Check an export job. |
|
|
426
|
+
|
|
427
|
+
#### Organization
|
|
428
|
+
|
|
429
|
+
`k9o.orgs` lists organizations and `k9o.org` administers the active one.
|
|
430
|
+
|
|
431
|
+
##### Organizations
|
|
432
|
+
|
|
433
|
+
| Method | What it does |
|
|
434
|
+
|---|---|
|
|
435
|
+
| `k9o.orgs.list` | List your organizations. |
|
|
436
|
+
| `k9o.orgs.get` | Read one by slug. |
|
|
437
|
+
| `k9o.orgs.current` | Read the active organization. |
|
|
438
|
+
| `k9o.orgs.restore` | Restore a deleted organization. |
|
|
439
|
+
|
|
440
|
+
##### Administration
|
|
441
|
+
|
|
442
|
+
| Method | What it does |
|
|
443
|
+
|---|---|
|
|
444
|
+
| `k9o.org.get` | Read the active organization. |
|
|
445
|
+
| `k9o.org.members.list` | List members. |
|
|
446
|
+
| `k9o.org.members.invite` | Invite a member by email and role. |
|
|
447
|
+
| `k9o.org.members.get` | Read one member. |
|
|
448
|
+
| `k9o.org.members.remove` | Remove a member. |
|
|
449
|
+
| `k9o.org.groups.list` | List groups. |
|
|
450
|
+
| `k9o.org.groups.create` | Create a group. |
|
|
451
|
+
| `k9o.org.groups.get` | Read one group. |
|
|
452
|
+
| `k9o.org.groups.delete` | Delete a group. |
|
|
453
|
+
| `k9o.org.audit_log.query` | Search organization audit events. |
|
|
454
|
+
| `k9o.org.gate.roles.list` | List role grants. |
|
|
455
|
+
| `k9o.org.gate.roles.grant` | Grant a role to a user. |
|
|
456
|
+
| `k9o.org.gate.roles.get` | Read one grant. |
|
|
457
|
+
| `k9o.org.gate.roles.revoke` | Revoke a grant. |
|
|
458
|
+
| `k9o.org.gate.idp_providers.list` | List identity providers. |
|
|
459
|
+
| `k9o.org.gate.idp_providers.create` | Add an identity provider. |
|
|
460
|
+
| `k9o.org.gate.idp_providers.get` | Read one provider. |
|
|
461
|
+
| `k9o.org.gate.idp_providers.configure` | Change a provider. |
|
|
462
|
+
| `k9o.org.gate.idp_providers.delete` | Remove a provider. |
|
|
463
|
+
| `k9o.org.smtp.get` | Read the mail server settings. |
|
|
464
|
+
| `k9o.org.smtp.set` | Save the mail server settings. |
|
|
465
|
+
| `k9o.org.smtp.test` | Send a test email. |
|
|
466
|
+
| `k9o.org.smtp.unset` | Remove the mail server settings. |
|
|
467
|
+
| `k9o.org.default_llm.get` | Read the default model. |
|
|
468
|
+
| `k9o.org.default_llm.set` | Set the default model. |
|
|
469
|
+
|
|
470
|
+
#### Vault secrets
|
|
471
|
+
|
|
472
|
+
`k9o.kibo.vault.secrets` stores and reveals secrets in the project's vault.
|
|
473
|
+
|
|
474
|
+
| Method | What it does |
|
|
475
|
+
|---|---|
|
|
476
|
+
| `k9o.kibo.vault.secrets.list` | List secrets by prefix. |
|
|
477
|
+
| `k9o.kibo.vault.secrets.get` | Read a secret's details. |
|
|
478
|
+
| `k9o.kibo.vault.secrets.create` | Store a new secret. |
|
|
479
|
+
| `k9o.kibo.vault.secrets.reveal_challenge` | Get a one-time challenge for revealing. |
|
|
480
|
+
| `k9o.kibo.vault.secrets.reveal` | Reveal the value using the challenge. |
|
|
481
|
+
| `k9o.kibo.vault.secrets.update` | Replace the value. |
|
|
482
|
+
| `k9o.kibo.vault.secrets.rotate` | Rotate the secret. |
|
|
483
|
+
| `k9o.kibo.vault.secrets.move` | Move to a new path. |
|
|
484
|
+
| `k9o.kibo.vault.secrets.delete` | Delete the secret. |
|
|
485
|
+
|
|
486
|
+
### Response metadata
|
|
487
|
+
|
|
488
|
+
| Field | What it holds |
|
|
489
|
+
|---|---|
|
|
490
|
+
| `meta.cursor` | Pagination: `next` and `total_count`. |
|
|
491
|
+
| `meta.context` | Request tracing: `request_id`. |
|
|
492
|
+
| `meta.timing` | Server time: `total_ms`. |
|
|
493
|
+
| `meta.warnings` | List of non-fatal warnings, each with `code` and `message`. |
|
|
494
|
+
| `meta.idempotency` | `replayed` flag for repeated requests. |
|
|
495
|
+
| `meta.subscription` | `is_initial` flag for streamed events. |
|
|
496
|
+
| `meta.cost` | Usage cost details as a hash. |
|
|
497
|
+
|
|
498
|
+
### Error attributes
|
|
499
|
+
|
|
500
|
+
| Attribute | Meaning |
|
|
501
|
+
|---|---|
|
|
502
|
+
| `code` | Error code such as `K9O_NOT_FOUND`. |
|
|
503
|
+
| `message` | Human-readable explanation. |
|
|
504
|
+
| `recommendation` | Suggested next step, or `nil`. |
|
|
505
|
+
| `status` | HTTP status, or `nil` if no request was made. |
|
|
506
|
+
| `request_id` | Server trace id. Quote it when contacting support. |
|
|
507
|
+
| `context` | Read-only details for the error. |
|
|
508
|
+
|
|
509
|
+
The server may send codes not listed here, so keep a fallback branch.
|
|
510
|
+
|
|
511
|
+
### Error codes
|
|
512
|
+
|
|
513
|
+
| Code | When |
|
|
514
|
+
|---|---|
|
|
515
|
+
| `K9O_INVALID_BASE_URL` | `base_url` has a path, query or bad scheme. |
|
|
516
|
+
| `K9O_MISSING_PROJECT_CONTEXT` | A project call was made without `project_slug`. |
|
|
517
|
+
| `K9O_INVALID_FIELD_VALUE` | An argument failed validation before sending. |
|
|
518
|
+
| `K9O_UPSTREAM_UNAVAILABLE` | Network failure reaching the gateway. |
|
|
519
|
+
| `K9O_INTERNAL_ERROR` | The response could not be read. |
|
|
520
|
+
|
|
521
|
+
`error.to_s` reads like `[K9O_NOT_FOUND] Collection not found (status=404)`.
|
|
522
|
+
|
|
523
|
+
### Retries
|
|
524
|
+
|
|
525
|
+
- GET, HEAD, OPTIONS and DELETE are retried on network errors.
|
|
526
|
+
- They are also retried on 429, 502, 503 and 504.
|
|
527
|
+
- The default is 3 retries with exponential backoff.
|
|
528
|
+
- Other methods are never retried.
|
|
529
|
+
|
|
530
|
+
### Regional hosts
|
|
531
|
+
|
|
532
|
+
- Organization hosts such as `https://acme.api.k9o.io` are region-free.
|
|
533
|
+
- The SDK sends one credential-free `HEAD` request to learn the region.
|
|
534
|
+
- Later requests go to the regional host.
|
|
535
|
+
- Any other base URL is used exactly as given.
|
|
536
|
+
|
|
537
|
+
### Related packages
|
|
538
|
+
|
|
539
|
+
| Package | What it is |
|
|
540
|
+
|---|---|
|
|
541
|
+
| `@k9o/core` | TypeScript SDK |
|
|
542
|
+
| `@k9o/cli` | Command-line tool |
|
|
543
|
+
|
|
544
|
+
## License
|
|
545
|
+
|
|
546
|
+
Apache-2.0 © Formelo Inc. See `LICENSE` and `NOTICE`.
|
data/k9o.gemspec
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/k9o/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'k9o'
|
|
7
|
+
spec.version = K9o::VERSION
|
|
8
|
+
spec.authors = ['Kilimanjaro']
|
|
9
|
+
spec.email = ['engineering@kilimanjaro.dev']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Kilimanjaro platform SDK for Ruby'
|
|
12
|
+
spec.description = 'Idiomatic Ruby SDK — create_client + data DSL + projects + KError. snake_case + raise K9o::KError.'
|
|
13
|
+
spec.homepage = 'https://kilimanjaro.dev'
|
|
14
|
+
spec.license = 'Apache-2.0'
|
|
15
|
+
|
|
16
|
+
spec.required_ruby_version = '>= 3.2.0'
|
|
17
|
+
|
|
18
|
+
# Platform gems: the publish pipeline sets K9O_GEM_PLATFORM (e.g. arm64-darwin,
|
|
19
|
+
# x86_64-linux) when building a gem that bundles the kibo ZK native lib for that
|
|
20
|
+
# platform. Unset → the pure-Ruby gem (the universal fallback; `k9o.kibo` is
|
|
21
|
+
# simply unavailable where no platform gem matches).
|
|
22
|
+
if (gem_plat = ENV['K9O_GEM_PLATFORM']) && !gem_plat.empty?
|
|
23
|
+
spec.platform = gem_plat
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
spec.metadata = {
|
|
27
|
+
'homepage_uri' => 'https://kilimanjaro.dev',
|
|
28
|
+
'source_code_uri' => 'https://github.com/k9o-dev/sdk-ruby',
|
|
29
|
+
'changelog_uri' => 'https://github.com/k9o-dev/sdk-ruby/blob/main/CHANGELOG.md'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Ruby sources + the CI-injected kibo native lib (one per platform gem; the
|
|
33
|
+
# generated uniffi binding under lib/k9o/_ffi/ is picked up by the .rb glob).
|
|
34
|
+
spec.files = Dir.glob('lib/**/*.rb') +
|
|
35
|
+
Dir.glob('lib/k9o/_ffi/*.{dylib,so,bundle,dll}') +
|
|
36
|
+
Dir.glob('sig/**/*.rbs') +
|
|
37
|
+
%w[README.md CHANGELOG.md LICENSE NOTICE k9o.gemspec]
|
|
38
|
+
spec.require_paths = ['lib']
|
|
39
|
+
|
|
40
|
+
spec.add_development_dependency 'minitest', '~> 5.20'
|
|
41
|
+
end
|
data/lib/k9o/ai.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module K9o
|
|
4
|
+
# AI namespace — platform AI primitives.
|
|
5
|
+
# k9o.ai.embed(...)
|
|
6
|
+
#
|
|
7
|
+
# Wire (project-plane):
|
|
8
|
+
# POST /@<slug>/ai/embeddings body { model?, input: String | [String] }
|
|
9
|
+
# -> { data: { embeddings: [[Float]], model:, dimensions: }, meta }
|
|
10
|
+
#
|
|
11
|
+
# Bounds are enforced by the gateway, not here. The SDK sends `input`
|
|
12
|
+
# exactly as given and never puts it in an error.
|
|
13
|
+
class Ai
|
|
14
|
+
def initialize(config)
|
|
15
|
+
@config = config
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# POST /@<slug>/ai/embeddings — embed one string or an array of strings.
|
|
19
|
+
# `model` is omitted from the body when nil (server default).
|
|
20
|
+
def embed(input:, model: nil)
|
|
21
|
+
slug = Studio.require_project_slug(@config, 'ai')
|
|
22
|
+
body = { 'input' => input }
|
|
23
|
+
body['model'] = model unless model.nil?
|
|
24
|
+
HttpTransport.request(config: @config, method: 'POST',
|
|
25
|
+
path: UrlGrammar.project_path(slug, 'ai/embeddings'), body: body)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/k9o/audit.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module K9o
|
|
4
|
+
# Project-plane audit log namespace — k9o.audit.*.
|
|
5
|
+
# Distinct from k9o.org.audit_log + k9o.me.audit_log.
|
|
6
|
+
class Audit
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Query the audit log (reverse-chronological; filters AND-compose).
|
|
12
|
+
# Accepts keyword filters: since/until/type/actor_id/target_kind/
|
|
13
|
+
# target_id/limit/cursor (wire camelCase mapping applied here).
|
|
14
|
+
def query(since: nil, until_: nil, type: nil, actor_id: nil,
|
|
15
|
+
target_kind: nil, target_id: nil, limit: nil, cursor: nil)
|
|
16
|
+
slug = Studio.require_project_slug(@config, 'audit')
|
|
17
|
+
q = {}
|
|
18
|
+
q['since'] = since if since
|
|
19
|
+
q['until'] = until_ if until_
|
|
20
|
+
q['type'] = type if type
|
|
21
|
+
q['actorId'] = actor_id if actor_id
|
|
22
|
+
q['targetKind'] = target_kind if target_kind
|
|
23
|
+
q['targetId'] = target_id if target_id
|
|
24
|
+
q['limit'] = limit if limit
|
|
25
|
+
q['cursor'] = cursor if cursor
|
|
26
|
+
HttpTransport.request(config: @config, method: 'GET', path: UrlGrammar.project_path(slug, 'audit-log'), query: q)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|