k9o 1.0.0 → 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 +4 -4
- data/CHANGELOG.md +5 -33
- data/README.md +518 -39
- data/lib/k9o/client.rb +1 -1
- data/lib/k9o/compute.rb +5 -5
- data/lib/k9o/data.rb +2 -2
- data/lib/k9o/envelope.rb +2 -2
- data/lib/k9o/http_transport.rb +5 -5
- data/lib/k9o/migrations.rb +2 -2
- data/lib/k9o/org.rb +3 -3
- data/lib/k9o/realtime.rb +6 -6
- data/lib/k9o/storage.rb +1 -1
- data/lib/k9o/studio.rb +5 -5
- data/lib/k9o/url_grammar.rb +2 -2
- data/lib/k9o/vault.rb +4 -4
- data/lib/k9o/version.rb +1 -1
- data/lib/k9o.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40ba93ba07b61c2255541b842d863f178c808a14aa818960f6f34c046ffa56a0
|
|
4
|
+
data.tar.gz: db5cbcf71af58764f38a50a3926897bf584911bdf25c3b2b0c75ce4565564b22
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e185588f9e7e453e008ec5ad828b941e79c647ad48645064374acf757b87fc38a9f384cf48a261d1273e8b947c0fd0f336afb3d744b4e8fa60d6f2424964adb8
|
|
7
|
+
data.tar.gz: 47a5f42f3c43d1bd00b0d2c8eaf1c9d6f0150aa85d9a288e49613fc2a796b3e05474b14d26e5c64b3c1259795d72544d9b3693834422a9252d51a88c14ed8409
|
data/CHANGELOG.md
CHANGED
|
@@ -1,38 +1,10 @@
|
|
|
1
1
|
# Changelog — k9o (Ruby)
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1.1.0 — 2026-10-25
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
-
|
|
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 rewritten with runnable examples and expected output; internal cross-references removed from the published sources. No change to the public API.
|
|
6
|
+
- Error text for `update()` / `delete()` without an `id` filter no longer mentions a version or a roadmap.
|
|
8
7
|
|
|
9
|
-
##
|
|
8
|
+
## 1.0.0 — 2026-10-23
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
NEW surfaces:
|
|
14
|
-
|
|
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.
|
|
10
|
+
First public release. See the README for the full API overview.
|
data/README.md
CHANGED
|
@@ -1,67 +1,546 @@
|
|
|
1
|
-
# k9o
|
|
1
|
+
# k9o
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Kilimanjaro platform SDK for Ruby.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Documentation: https://kilimanjaro.dev. Platform API: https://api.k9o.io.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Contents
|
|
8
8
|
|
|
9
|
-
|
|
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
|
|
10
18
|
|
|
11
19
|
```bash
|
|
12
20
|
gem install k9o
|
|
13
21
|
```
|
|
14
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
|
+
|
|
15
31
|
## Quick start
|
|
16
32
|
|
|
33
|
+
The examples use a `tasks` collection with `title` and `done` fields.
|
|
34
|
+
|
|
35
|
+
### Create the client
|
|
36
|
+
|
|
17
37
|
```ruby
|
|
18
|
-
require
|
|
38
|
+
require "k9o"
|
|
19
39
|
|
|
20
40
|
k9o = K9o.create_client(
|
|
21
|
-
base_url: "https://acme.api.k9o.io",
|
|
22
|
-
api_key: ENV["K9O_API_KEY"],
|
|
23
41
|
org_slug: "acme",
|
|
24
|
-
project_slug: "
|
|
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")
|
|
25
109
|
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The base URL rules are listed under [regional hosts](#regional-hosts).
|
|
113
|
+
|
|
114
|
+
## Running queries
|
|
26
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
|
|
27
143
|
begin
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
puts "
|
|
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
|
|
144
|
+
k9o.from("missing").select.execute
|
|
145
|
+
rescue K9o::KError => error
|
|
146
|
+
puts "#{error.code} #{error.status} #{error.request_id}"
|
|
147
|
+
puts error.message
|
|
37
148
|
end
|
|
38
149
|
```
|
|
39
150
|
|
|
40
|
-
|
|
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. |
|
|
41
497
|
|
|
42
|
-
|
|
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 |
|
|
43
514
|
|---|---|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
50
|
-
|
|
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) |
|
|
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)`.
|
|
56
522
|
|
|
57
|
-
|
|
523
|
+
### Retries
|
|
58
524
|
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
|
|
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 |
|
|
64
543
|
|
|
65
544
|
## License
|
|
66
545
|
|
|
67
|
-
|
|
546
|
+
Apache-2.0 © Formelo Inc. See `LICENSE` and `NOTICE`.
|
data/lib/k9o/client.rb
CHANGED
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
|
|
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
|
|
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
|
|
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)
|
|
49
|
-
# Enumerator of chunk hashes (
|
|
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;
|
|
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;
|
|
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
|
|
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
|
|
21
|
+
# Meta accessor sugar.
|
|
22
22
|
class Meta
|
|
23
23
|
attr_reader :cursor, :subscription, :idempotency, :warnings, :cost, :timing, :context
|
|
24
24
|
|
data/lib/k9o/http_transport.rb
CHANGED
|
@@ -6,7 +6,7 @@ require 'uri'
|
|
|
6
6
|
require_relative 'multipart'
|
|
7
7
|
|
|
8
8
|
module K9o
|
|
9
|
-
# Retry + backoff policy
|
|
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
|
|
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
|
|
214
|
-
#
|
|
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
|
|
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}"
|
data/lib/k9o/migrations.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module K9o
|
|
4
4
|
# Migration lifecycle namespace — k9o.migrations.*.
|
|
5
5
|
#
|
|
6
|
-
# TYPE MODEL (
|
|
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
|
|
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
|
|
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.*
|
|
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
|
|
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
|
|
7
|
-
# `.each`. Per
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
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
|
|
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
|
|
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)
|
|
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
|
|
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
|
|
119
|
+
# k9o.studio.dashboards.*.
|
|
120
120
|
class Dashboards
|
|
121
121
|
def initialize(config)
|
|
122
122
|
@config = config
|
data/lib/k9o/url_grammar.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require 'uri'
|
|
4
4
|
|
|
5
5
|
module K9o
|
|
6
|
-
# URL grammar
|
|
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
|
|
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
|
|
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
|
|
210
|
-
# (
|
|
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,
|
|
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
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)
|
|
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.
|
|
4
|
+
version: 1.1.0
|
|
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-
|
|
11
|
+
date: 2026-10-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|