k9o 1.5.0-arm64-darwin

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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +132 -0
  3. data/LICENSE +201 -0
  4. data/NOTICE +4 -0
  5. data/README.md +1946 -0
  6. data/k9o.gemspec +42 -0
  7. data/lib/k9o/_ffi/kibo_kms_rest_ffi.rb +2815 -0
  8. data/lib/k9o/_ffi/libkibo_kms_rest_ffi.dylib +0 -0
  9. data/lib/k9o/ai.rb +43 -0
  10. data/lib/k9o/analytics.rb +403 -0
  11. data/lib/k9o/approvals.rb +253 -0
  12. data/lib/k9o/audit.rb +177 -0
  13. data/lib/k9o/barbican.rb +239 -0
  14. data/lib/k9o/client.rb +78 -0
  15. data/lib/k9o/compute.rb +84 -0
  16. data/lib/k9o/crypto.rb +471 -0
  17. data/lib/k9o/custody.rb +28 -0
  18. data/lib/k9o/data.rb +277 -0
  19. data/lib/k9o/ed25519.rb +182 -0
  20. data/lib/k9o/end_users.rb +93 -0
  21. data/lib/k9o/envelope.rb +79 -0
  22. data/lib/k9o/functions.rb +169 -0
  23. data/lib/k9o/gate.rb +94 -0
  24. data/lib/k9o/http_transport.rb +380 -0
  25. data/lib/k9o/jcs.rb +117 -0
  26. data/lib/k9o/kerror.rb +104 -0
  27. data/lib/k9o/keys.rb +131 -0
  28. data/lib/k9o/kibo.rb +114 -0
  29. data/lib/k9o/kibo_client_core.rb +385 -0
  30. data/lib/k9o/kibo_ffi_core.rb +178 -0
  31. data/lib/k9o/locate.rb +118 -0
  32. data/lib/k9o/me.rb +100 -0
  33. data/lib/k9o/metadata.rb +342 -0
  34. data/lib/k9o/migrations.rb +244 -0
  35. data/lib/k9o/moat.rb +443 -0
  36. data/lib/k9o/multipart.rb +42 -0
  37. data/lib/k9o/org.rb +226 -0
  38. data/lib/k9o/orgs.rb +34 -0
  39. data/lib/k9o/policies.rb +84 -0
  40. data/lib/k9o/projects.rb +68 -0
  41. data/lib/k9o/query.rb +174 -0
  42. data/lib/k9o/rampart.rb +273 -0
  43. data/lib/k9o/realtime.rb +309 -0
  44. data/lib/k9o/region.rb +97 -0
  45. data/lib/k9o/schedules.rb +109 -0
  46. data/lib/k9o/schema.rb +35 -0
  47. data/lib/k9o/storage.rb +176 -0
  48. data/lib/k9o/streams.rb +94 -0
  49. data/lib/k9o/studio.rb +185 -0
  50. data/lib/k9o/url_grammar.rb +139 -0
  51. data/lib/k9o/vault.rb +230 -0
  52. data/lib/k9o/vectors.rb +124 -0
  53. data/lib/k9o/version.rb +5 -0
  54. data/lib/k9o.rb +71 -0
  55. data/sig/k9o/ai.rbs +20 -0
  56. data/sig/k9o/approvals.rbs +71 -0
  57. data/sig/k9o/datasets.rbs +125 -0
  58. data/sig/k9o/gate.rbs +14 -0
  59. data/sig/k9o/kerror.rbs +24 -0
  60. data/sig/k9o/kibo_client_core.rbs +25 -0
  61. data/sig/k9o/metadata.rbs +54 -0
  62. data/sig/k9o/migrations.rbs +138 -0
  63. data/sig/k9o/moat.rbs +29 -0
  64. data/sig/k9o/query.rbs +26 -0
  65. data/sig/k9o/rampart.rbs +59 -0
  66. data/sig/k9o/realtime.rbs +34 -0
  67. data/sig/k9o/region.rbs +30 -0
  68. data/sig/k9o/storage.rbs +41 -0
  69. data/sig/k9o/workload.rbs +64 -0
  70. metadata +130 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 78d7031c4fd2384c300666f52027387bfde576f78638f53797916f111b213334
4
+ data.tar.gz: 173cd23e945a1dae269486e48d79e8efe200794fc0b62a170bf050638294c6a8
5
+ SHA512:
6
+ metadata.gz: b1b30eeab1d44672b521eaf75f2e36ff0484393e8de90d80fd28a3cba2f641aa0c5940645d354b9fa81ef4030fee7921af88cade85a9e6866557f2bfe3979b76
7
+ data.tar.gz: 25f87e0d1bce9bc2825c053f401e70d7b074b1cb0a639a96a62b708ae76c711ed68061b6d1a2380738c2e713d5bad8fea20e9c706839ed008c2a6f6591ed8a1b
data/CHANGELOG.md ADDED
@@ -0,0 +1,132 @@
1
+ # Changelog — k9o (Ruby)
2
+
3
+ ## 1.5.0 (unreleased)
4
+
5
+ ### Added
6
+
7
+ - `approvals.comments.add(pending_id, body:, visibility:)` and `approvals.comments.list(pending_id, limit: nil, cursor: nil)`: comment on a pending change (`POST` and `GET /@<project>/pending-approvals/<id>/comments`). `body` is 1 to 4000 characters and `visibility` is `"everyone"` or `"approvers_only"`, fixed once posted; `pending_id`, `body`, `visibility` and `limit` (1 to 200) are checked before anything is sent (`K9O_INVALID_FIELD_VALUE`). `list` answers the comments the caller may see, oldest first, as a page with `next_cursor` (`nil` on the last page). Posting needs a session; a personal access token alone is refused (`K9O_RBAC_DENY`). `K9O_APPROVAL_COMMENT_NOT_ELIGIBLE` and `K9O_APPROVAL_COMMENT_CLOSED` arrive as `K9o::KError`.
8
+ - `realtime.replay(topic, from_sequence: nil, until_sequence: nil, limit: nil)`: read a batch of past events for a realtime topic (`POST /@<project>/realtime/replay`), the catch-up for `realtime.subscribe`. `topic` is required; `from_sequence` and `until_sequence` are whole numbers (0 or more) and `limit` is 1 to 10000 (`K9O_INVALID_FIELD_VALUE` before anything is sent). `data` is `{ "events", "nextCursor", "hasMore" }`, plus `"resync"` (`"reread-source"`) when the topic keeps no history, so re-read the current state. Events keep the gateway's spelling that `subscribe` yields. `audit.replay` is unchanged.
9
+ - `gate.sign_in` asks the project which region holds the email first (`POST /@<project>/gate/locate`, the email only, no credential) and sends the password to that region's host. The located host is used only if it is `https`, has no userinfo, port, path, query or fragment, and is your own org, gateway family and apex with the region code added or swapped in; otherwise the base URL is used. The answer is never cached; `refresh_token` and `sign_out` go to the host that issued the session, from a bounded in-memory hint. If the locate step answers 404, the base URL is used. A 429 `K9O_RATE_LIMITED` or 503 `K9O_GATE_REGION_UNAVAILABLE` from that step raises as `K9o::KError`, nothing else is sent, and the call is safe to retry.
10
+ - `crypto.mode` and `crypto.mode(crypt:)` return the gateway's `route` (`"client"` or `"server"`) as `Mode#route`, `nil` on older gateways or for an unknown value; follow it, not `custody_mode`.
11
+ - The custody check before each `crypto.encrypt` names the crypt (`GET /crypto/mode?crypt=<crypt>`), so a personal access token or workload policy scoped to named crypts can encrypt. `crypto.mode` sends no query.
12
+ - `crypto.mode(crypt: nil)`: an optional crypt for the public mode read (`GET /crypto/mode?crypt=<crypt>`); the crypt is checked before sending (`K9O_INVALID_FIELD_VALUE`), and `crypto.mode` is unchanged.
13
+ - `crypto.encrypt` follows the `route` in the project's mode answer. On a BYOK or HYOK project only an explicit route `"server"` sends plaintext to the platform (the answer then needs an epoch, otherwise `K9O_CRYPTO_CUSTODY_UNKNOWN`); a missing route uses your client core. A route that is not `"server"` or `"client"` raises `K9O_CRYPTO_CUSTODY_UNKNOWN` and nothing is sent. The mode is read on every call. `decrypt` and `rewrap` are unchanged.
14
+ - `crypto.crypts_list`, `crypto.crypts_create(name)` and `crypto.crypts_retire(name)`: list, register and retire crypt names. `create` sends only `{ name }`; a name outside 1 to 64 characters of a-z, 0-9 and `-` (or `actions`) raises `K9O_INVALID_FIELD_VALUE` (`field: name`) before anything is sent. Each answers a crypt as `{ "name", "status" ("active" or "retired"), "createdAt", "retiredAt" }`; a malformed gateway answer raises `K9O_INTERNAL_ERROR`. `K9O_CRYPT_ALREADY_EXISTS`, `K9O_CRYPT_LIMIT_EXCEEDED`, `K9O_CRYPT_RETIRED`, `K9O_CRYPT_NOT_FOUND` and access refusals arrive as `K9o::KError`. A retired or unregistered name only makes `encrypt` refuse it; `decrypt` and `rewrap` never read the registry. Needs `crypto:manage_crypts` (project admins by default); a personal access token is refused on retire.
15
+ - `K9o::KiboClientCore`: the client core for `k9o.crypto` on a BYOK or HYOK project. It opens and seals data on this machine against your own KMS or HSM, so the platform never sees plaintext or the key. Register it with `crypto.use_client_core`. The key, provider, region, role and endpoint all come from the configuration you pass; `expected_key_refs:` is required and non-empty, and the configured key must be in it. Before any token is fetched it checks that the bound core lists `expected_key_refs` (otherwise `K9O_CRYPTO_KEY_PIN_UNENFORCED`) and exports the 2.15.0 functions (otherwise `KIBO_WASM_ERROR`). A federated-token response that names another provider or project is refused with `K9O_INVALID_FIELD_VALUE` and nothing is exchanged. The exchange has a deadline (30 s, `exchange_deadline:`; `KIBO_EXCHANGE_TIMEOUT`); the exchanged credential is reused until 60 s before it expires, and a federated token is fetched on every call. A failed item is `{ "ok" => false, "code", "message" }` with the core's code (`UPSTREAM_KMS_ERROR` is your own KMS); a pin, capability, token or exchange problem raises `K9o::KError`. No token or credential appears in an error, `inspect` or `to_s`. A call whose own `expected_key_refs` does not contain the configured key is refused per item with `K9O_CRYPTO_UNEXPECTED_KEY` before the federated token is fetched and before the exchange.
16
+ - `K9o::KiboFfiCore`: a built-in bound core for `K9o::KiboClientCore` that works with the generated Ruby binding (`KiboKmsRestFfi`, zk-bundle-v2.16.3 or later). Pass `core: K9o::KiboFfiCore.new`. It converts the SDK's plain data to the binding's typed records, integer enums and federation variant, and the binding's errors to `CODE: detail` (`UPSTREAM_KMS_ERROR` for your own KMS failing); the cryptography stays in the native core. Requiring `k9o` does not load the binding; building the adapter without it raises `K9o::KError` (`KIBO_WASM_ERROR`). `library:` takes the absolute path of the native library, `binding_path:` the path of the binding file. The Vault federation field for the JWT login is `jwt_auth_mount` (the name Vault serves the JWT login under, `jwt` for `auth/jwt`; not the transit mount); the core receives it as its own `mount` field, and `vault_addr`, `jwt_auth_mount` and `role` are required for `provider: "vault"`.
17
+ - `K9o::Crypto::FederatedToken#provider` and `#project_id`: set when the gateway names them in the federated-token response, otherwise `nil`. They are only checked against your configuration.
18
+ - `crypto.federated_token(crypt, op)`: ask for a short-lived RS256 token (valid for at most 15 minutes) for one crypt and one operation (`"encrypt"`, `"decrypt"` or `"rewrap"`), answered as `K9o::Crypto::FederatedToken` (`token`, `expires_at`, `issuer`, `subject`, `audience`, `kid`). `crypt` and `op` are checked before sending (`K9O_INVALID_FIELD_VALUE`); the call is never retried; a response without any of the six fields raises `K9O_INTERNAL_ERROR`. The token is left out of `inspect`, `to_s` and `pp`.
19
+ - `expected_key_refs:` client option: an `Array` of the key identifiers (from your own cloud configuration) your BYOK or HYOK key may be. It is checked when the client is built (non-empty, no blanks, spaces or `*`; `K9O_INVALID_FIELD_VALUE` otherwise) and passed to the client core as the keyword `expected_key_refs:` on every `crypto.encrypt`, `decrypt` and `rewrap` call when set, so the core refuses any other key (version ignored) before it uses a token or makes a network call. A core declares that it does with a method `enforces_expected_key_refs?` that returns `true`; with the option set and no declaration the call raises `K9O_CRYPTO_KEY_PIN_UNENFORCED` before the core is called. `K9o::Crypto.key_ref_matches?(key_ref, expected, provider:)` is the comparison for core authors (`provider:` is required, one of `:aws`, `:gcp`, `:azure` or `:vault`, and is never guessed from the reference): AWS compares the whole reference; GCP without the version; Azure the first five parts in lower case; Vault `<path>/<key>` without `:<version>`.
20
+ - `custody.status`: read how the project's keys are held (`mode`, `attached`, `provider`, `lastJob`, and `hsm` for a hardware security module); read-only.
21
+ - `KError#retry_after_sec`: the wait the gateway asks for (seconds), or `nil`.
22
+ - `KError#request_id` is filled from the gateway's `x-k9o-request-id` response header (any letter case) when the error body carries no request id, on every error built from a non-2xx response, including a stream open; a request id in the body still wins, and it stays `nil` when neither is present.
23
+ - `require_approval` on single-record writes: `insert(record, require_approval: true)`, and `.require_approval` on `update` and `delete` builders. The write is sent with `?requireApproval=true` and may answer a queued change (HTTP 202); `K9o.queued_write?(result)` tells it from an applied row. `Meta#approval` carries `meta.approval`.
24
+ - `functions.triggers`: `list`, `create`, `update` and `delete` for event triggers.
25
+ - `schedules` namespace: `list`, `get`, `create`, `update`, `delete`, `runs` and `run_now`.
26
+ - `vectors` namespace: `nearest` and `upsert` for vector collections (names start with `_`), sending the embedding in the request body.
27
+ - `metadata` namespace: `filter`, `set`, `search`, `vectors.nearest`, `subscribe`, and `index.get` / `index.declare` for the columns you declare on a collection. Column names in `where`, `search` and `nearest` get the `metadata.` prefix when you leave it out; `set` writes declared columns only. `subscribe` uses the same reconnecting reader as `realtime.subscribe` (events carry the record id only) and takes `from_sequence:`. The SDK checks the surface grammar, limits, cursor rule and the 64-column limit before sending. Gateway codes such as `K9O_METADATA_FIELD_NOT_INDEXED`, `K9O_UNKNOWN_SURFACE` and `K9O_QUERY_RESULT_TOO_LARGE` arrive as `K9o::KError`.
28
+ - `rampart` namespace: `classify(input, label:)` answers the verdict and its signed receipt (advisory; a classifier outage raises `K9O_RAMPART_CLASSIFIER_UNAVAILABLE`), `jwks` reads the public key feed, and `verify_receipt(result_or_receipt, input)` checks a receipt locally (EdDSA, `typ`, issuer, project, clock skew, and the SHA-256 of the canonical `input`) and returns the verified verdict or raises `K9o::Rampart::ReceiptRefusal` with a closed `reason`. The issuer comes from the key feed (`issuer:` overrides it); the project is the `projectId` of the `classify` result (or `project_id:`), and a bare receipt string with neither is refused as `project_unknown`. Keys are cached for the client's life and refetched once on an unknown key id. `K9o::Jcs` (the platform's canonical form: keys sorted by UTF-8 byte order, integers only up to 2^53 - 1, so an input with a fractional number cannot be classified or verified) and `K9o::Ed25519` (openssl, with a built-in fallback) are included, with no new dependency. A long input is scored in overlapping windows and the highest injection score decides; past 16 windows (about 6,000 tokens) the answer is `413 K9O_RAMPART_INPUT_TOO_LONG` with no verdict, and `503 K9O_RAMPART_CLASSIFIER_UNAVAILABLE` still means the classifier could not answer. The thresholds (calibration `rampart-launch-v1`) are a starting calibration and may move; a change is a new `calibrationVersion`.
29
+ - `analytics` namespace for datasets: `list`, `query`, `create`, `get`, `delete`, `materialize`, `read` (cursor paging), `write`, `upload` (raw or multipart with a manifest), `download_original` (answers a `K9o::Download`), plus `analytics.rollups` and `analytics.schedules` (`create`, `list`, `delete`, `reattest`) and the project-wide `rollups` namespace (`list`, `read`, `subscribe`). `reattest` is for people only: a service, workload or extension token gets `403 K9O_RBAC_DENY` (`reason: human_only`), and a rollup or schedule that is not re-attested pauses when its interval ends.
30
+ - `keys` namespace: `list`, `get` and `rotate` for the project's encryption keys (metadata only; `list` takes `status:` `active` or `all` and is not paged). `rotate(key_id, step_up: hook)`: on `401 K9O_STEP_UP_REQUIRED` the SDK calls your hook with the challenge (`KError#step_up`), the HTTP method and the URL, sends the same request once more with the `x-k9o-step-up-proof` header built from its `{ method:, proof: }` answer, and never loops; without a hook the error carries the challenge. Rotation is never retried otherwise, and answers `409 K9O_STATE_CONFLICT` or `429 K9O_RATE_LIMITED` (at most 3 per rolling 24 hours) as `K9o::KError`.
31
+ - `audit.tail(types:, on_resync:)`: live audit events (`auditEventId`, `type`, `actorType`, `occurredAt`, `outcome`, and the frame's `eventId`) read from the gateway's frames (the audit event sits in `payload`; the frame's SSE `id` is the publisher's own id and the `Last-Event-ID` for a resume), on the reconnecting reader of `realtime.subscribe`; on a `replay-ledger` resync it reads the missed events through the new `audit.replay` after the last `auditEventId` delivered, page by page, and yields them once. `audit.replay` answers the typed page `{ events, nextCursor, hasMore }` (events flattened, `sequence` a string).
32
+ - `audit.tail` after a `resync` is gapless: it reconnects fresh and buffers that connection, replays from the last delivered `auditEventId`, then merges replay, buffered and live frames, each event once (a repeated resync backs off). `audit.replay` sends `limit: 1000` when you give none and refuses a limit above 10000 or below 1 with `K9O_INVALID_FIELD_VALUE`. A new connection starts at the live head and may re-send the last few seconds of events (each yielded once), and the informational `resync` that opens it is ignored.
33
+ - `rollups.subscribe` yields the cell from each `cell` frame's `payload` (with `eventId` and a `suppressed` flag for cells below the cohort threshold), resumes with the frame's `id`, and calls `on_resync` on `reread-source`.
34
+ - `crypto` namespace for server-side encryption with the project's key: `encrypt`, `decrypt` and `rewrap` (`POST /crypto/encrypt|decrypt|rewrap`), batches of up to 100 items, bytes in and out with the base64 done for you, `K9o::Crypto.text`, and client-side checks (`K9O_INVALID_FIELD_VALUE`, `K9O_PAYLOAD_TOO_LARGE`) before anything is sent. Never retried automatically. `encrypt` checks the custody mode (`crypto.mode`) on every call and never sends plaintext when the key is in your own KMS or HSM; `decrypt` and `rewrap` try the platform first and reroute client-side on `409 K9O_ZK_STORE_FLOW_REQUIRED`. Register the Kibo client core with `crypto.use_client_core`; without one those calls raise `K9O_ZK_CLIENT_CORE_UNAVAILABLE` (501). An unknown mode or a failed check raises and sends nothing. The gateway route is not live yet.
35
+ - `Rampart::Verdict#windows`: the number of windows the classifier scored, read from the signed `windows` claim (`nil` when absent); unknown claims are ignored. `413 K9O_RAMPART_INPUT_TOO_LONG` raises as `K9o::KError`.
36
+ - `KError#retry_after_sec` also reads the `Retry-After` response header (whole seconds) when the body gives none.
37
+ - `K9o::Moat`: a local guard for one model call with no network access. It pins the system prompt, refuses role and system markers in untrusted input, checks input and output against a documented JSON Schema subset, and runs an optional PII filter you pass in. Refusals raise `K9o::Moat::Refusal` with `reason` `role_marker`, `input_schema`, `output_schema` or `pii`.
38
+ - `K9o::Moat` role-marker scan follows the shared normalisation rule: NFKC, combining marks ignored, default-ignorable and format code points removed, a small set of Cyrillic and Greek look-alikes of the marker letters read as the Latin letter (not general homoglyph detection), case-folded, horizontal whitespace collapsed, then matched line by line; it passes the shared marker vectors.
39
+ - `end_users` namespace: `list`, `get` and `role_grants` (`list`, `grant`, `revoke`).
40
+ - `approvals.list` pages: optional `cursor:` (from `meta.cursor.next`, `nil` on the last page) beside `status:` and `limit:`.
41
+ - `approvals.bulk` result carries `failed`, a list of `{ "id", "code", "reason" }` for rows that did not apply (empty when none); the call answers HTTP 200 even when rows fail.
42
+
43
+ - `realtime.subscribe` resumes: it reconnects with `Last-Event-ID` when the stream ends or the network fails (backoff up to 30 seconds), drops duplicate events by `eventId`, ignores heartbeats, abandons a connection idle for 45 seconds, and calls the new optional `on_resync:` handler (without yielding the frame) before continuing from a fresh connection. Events carry `eventId`.
44
+ - README: what an event-trigger function receives (the JSON payload, redaction, `triggeredAt`, and deduping on `eventId`).
45
+
46
+ ### Changed
47
+
48
+ - The read timeout is 120 seconds (was 30), as in the Python SDK, so a long call such as Rampart `classify` on a long input is not cut off. A client you pass in with `http_client:` keeps being set to the same value.
49
+
50
+ - `vector_search` on the select builder sends the embedding in the request body (`POST data/<collection>/search`), so real embeddings work. It cannot be combined with `text_search`.
51
+ - The approval policies README no longer says the builders do not send `requireApproval`.
52
+
53
+ ### Fixed
54
+
55
+ - `realtime.subscribe`, `metadata.subscribe` and `rollups.subscribe` no longer reconnect forever on a fresh connection. The gateway opens such a connection with an informational `event: resync` frame and then streams events on the same connection; the reader treated that frame as a lost position, so no event was delivered. A `resync` that is the first data of a connection sent with no `Last-Event-ID` and no `fromSequence` is now ignored (`on_resync` is not called and the connection is kept). A `resync` after an event, or on a connection sent with `Last-Event-ID` or `fromSequence`, is still a lost position: `on_resync` is called and the reader reconnects fresh. `audit.tail` is unchanged.
56
+ - `require "k9o"` no longer fails on Ruby 3.4 and later with `cannot load such file -- base64`: the vault code encodes and decodes base64 without the `base64` gem, which is no longer a default gem there and was not declared as a dependency.
57
+ - `audit.tail` and `audit.replay` read the gateway's real frames: the tail used to deliver no events, and a replay returned an empty list, because the decoders looked for the five audit fields at the top of the frame and took the SSE `id` for the audit event id. `rollups.subscribe` yielded the frame, not the cell.
58
+ - `Rampart#classify` raises `K9O_INVALID_FIELD_VALUE` for an `input` that is not a Hash, with a test; the gateway is going to refuse it with a 400.
59
+ - `keys.list` no longer exposes `nextCursor` (the list is not paged).
60
+
61
+ - `KError#recommendation` is always a string or `nil`. An object recommendation from the gateway (`{"action": ...}` or `{"retryAfterSec": ..., "note": ...}`) used to arrive as a Hash; it now gives its `action`, else its `note`.
62
+
63
+ ## 1.4.0 — 2026-10-26
64
+
65
+ ### Added
66
+
67
+ - `query(sql, params)`: one read-only SQL statement; an array binds `$1, $2, ...`, a hash binds `:name` placeholders.
68
+ - `search(collection, column:, q:)`: full-text search over one column, plus `text_search` and `vector_search` on `select`.
69
+ - `ai.generate`: text generation from a prompt (verb sugar over `compute.llms.invoke`; `model` defaults to the org's default LLM).
70
+ - `streams` namespace for user data streams: `create`, `list`, `get`, `delete`, `publish`, `replay` and `subscribe`.
71
+ `subscribe` tails live events over SSE and reconnects from the last sequence when the server closes the connection.
72
+
73
+ - `approvals` namespace for the pending-change queue: `list`, `get`, `approve`, `reject` and `bulk`.
74
+ - `approval_policies` namespace: `list`, `create` and `delete`.
75
+ - `schema.collections.list`: the project's collections with row counts and last migration, paged by cursor.
76
+
77
+ ### Changed
78
+
79
+ - The README description now covers streams and realtime, and the platform overview moved to an "About Kilimanjaro" appendix.
80
+ - Function deploy examples use the sandbox tier.
81
+
82
+ ## 1.3.0 — 2026-10-26
83
+
84
+ Every method now matches the gateway.
85
+
86
+ ### Changed
87
+
88
+ - `projects.create` takes `display_name:` (and optional `slug:`, `region:`, `custody_mode:`, ...);
89
+ `projects.get` and `projects.update` use the projects routes.
90
+ - `functions.deploy` takes `name:`, `runtime:`, `tier:` (`gateway` or `sandbox`), `artifact_key:`, `version:` and `description:`.
91
+ Inline code is gone.
92
+ - `functions.invoke` sends the payload as `{payload}`.
93
+ - `policies.create`, `update` and `validate` take a `policy:` document (plus optional `rules:`, `editor_mode:`);
94
+ `policies.list` takes only `status:`.
95
+ - `audit.query` filters are `event_type:`, `actor_id:`, `after:`, `before:`, `limit:` and `cursor:`.
96
+ - Org roles, identity providers and default model use the current routes; `smtp.set` uses `password_ref:` and `from_address:`;
97
+ `smtp.test` takes `to:` and `subject:`.
98
+ - `me.api_tokens.create` takes `label:` and `scope_manifest:` (and `ttl_seconds:`); `me.sessions.revoke` and `revoke_all` use new routes.
99
+ - `compute.llms.invoke` settings are sent flat, and the result has `content` and `usage`.
100
+ - `studio.workflows.trigger` sends the context as `triggerContext`.
101
+ - `gate.sign_out` requires the refresh token.
102
+ - The API host comes from the base URL: any `<org>.api.<apex>` host works and no apex is hardcoded.
103
+ `https://api.k9o.io` is only the default.
104
+
105
+ ### Removed
106
+
107
+ - `gate.verify_session`, `gate.hosted`, `realtime.replay` and `realtime.subscribe_poll`.
108
+ - `me.notifications`, `me.audit_log` and `me.data_export`.
109
+ - `org.groups.create`, `org.groups.delete`, `org.members.get` and `org.smtp.get`.
110
+
111
+ ### Added
112
+
113
+ - `functions.upload_artifact(bytes, kind)` uploads a build and returns the `artifactKey` for `deploy`.
114
+ - `UrlGrammar.parse_api_host` reads the org, region and apex from any gateway host.
115
+ - A contract test checks every method against the gateway's API description.
116
+
117
+ ## 1.2.0 — 2026-10-25
118
+
119
+ - The README now introduces the Kilimanjaro building blocks (Keep, Pulse, Gate, Kibo). No change to the public API.
120
+
121
+ ## 1.1.1 — 2026-10-25
122
+
123
+ - 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.
124
+
125
+ ## 1.1.0 — 2026-10-25
126
+
127
+ - Documentation rewritten with runnable examples and expected output; internal cross-references removed from the published sources. No change to the public API.
128
+ - Error text for `update()` / `delete()` without an `id` filter no longer mentions a version or a roadmap.
129
+
130
+ ## 1.0.0 — 2026-10-23
131
+
132
+ First public release. See the README for the full API overview.
data/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
data/NOTICE ADDED
@@ -0,0 +1,4 @@
1
+ Kilimanjaro SDK
2
+ Copyright 2026 Formelo Inc.
3
+
4
+ This product is licensed under the Apache License, Version 2.0 (see LICENSE).