Skip to content

Kindgi 0.1.8

View as Markdown

Released October 16, 2026. For the docs of this version, see docs.kindgi.com/v0.1.8.

  • A key limited to a project could file a conversation outside it. A conversation started with a key limited to a project (--project) that named no project was filed in the tenant's default project, not the key's: the key couldn't read it afterwards, and the default project's readers could. A run continuing that conversation was filed there too. In 0.1.8 a conversation that names no project goes to the key's project, and a key can't continue a conversation outside its project (403 key-project-mismatch). 0.1.5 to 0.1.7 are affected (API keys).
  • Some clouds' metadata addresses weren't refused. Kindgi refuses a cloud's metadata address wherever tenant configuration names a host (at KINDGI_TENANT_HOST_ACCESS=deployed and above) and in a webhook's URL outside development mode. Before 0.1.8 it refused only link-local addresses and AWS's IPv6 one, not the others that clouds document: Azure's WireServer (168.63.129.16), Alibaba Cloud's metadata service (100.100.100.200), the EKS Pod Identity Agent (fd00:ec2::23), Compute Engine's for IPv6-only VMs (fd20:ce::254), Akamai's (Linode's, fd00:a9fe:a9fe::1) and Scaleway's (fd00:42::42). Azure's counted as a public address, so a host or a webhook could name it at every level; the others counted as private, so a host could name them at deployed, and a webhook under KINDGI_WEBHOOK_PRIVATE_NETWORKS=allow. In 0.1.8 they're refused wherever link-local addresses are, and an IPv4 address written inside an IPv6 one as IPv4-translated (::ffff:0:a.b.c.d) is read as that IPv4 address, as the other forms already were. These ranges, which no service is reached at, are refused too: 192.88.99.0/24, 2001:2::/48, 2001:10::/28, 3fff::/20, 5f00::/16 and 100:0:0:1::/64. Every release before 0.1.8 is affected.
    • A webhook URL refused for a link-local or metadata address now says "link-local and cloud metadata addresses are not allowed". Under KINDGI_WEBHOOK_PRIVATE_NETWORKS=allow, the other refusals say "loopback and reserved addresses are not allowed", where they said "loopback, link-local and reserved addresses are not allowed". A script that matches the old words needs the new ones.
  • The S3-compatible routes read a whole upload before checking its signature. @kindgi/api serves S3-compatible routes (/s3/*) to an app that embeds it and sets its s3Credentials option. They read a request's whole body into memory before they checked its signature, so a caller with no credentials could make the server hold a body of any size. Kindgi's runtime doesn't serve these routes, self-hosted or hosted. In 0.1.8 the signature is checked first, from the headers, and the body is read only up to artifactMaxBytes (100 MiB by default): a larger one is refused with S3's 400 EntityTooLarge. A larger object goes up as a multipart upload, each part under the limit. A header-signed body is checked against its x-amz-content-sha256 when it's empty too. @kindgi/api 0.1.8 needs hono 4.13.8 or later.
  • A tenant's policies were skipped when they couldn't be read. If reading a tenant's policies failed, such as on a database error, the tenant was treated as having none. A turn ran without its approval, model-routing and tool-errors policies, and a removed model provider that a retention policy keeps for good could be deleted with its adapter. In 0.1.8 such a read fails instead: the turn fails, nothing is deleted, and the policies API answers 500 rather than an empty list. Every release before 0.1.8 is affected; the provider deletion, 0.1.4 to 0.1.7.
  • Tenants that don't trust one another: a new level, KINDGI_TENANT_HOST_ACCESS=isolated, is for a runtime whose tenants don't trust one another. It refuses all that deployed does, and also private networks wherever tenant configuration names a host. A model provider can't sign in with the runtime's own cloud credentials there: Gemini on Vertex AI needs a service-account key in secret_ref, and Bedrock's auth: aws-identity (the bedrock preset's default) and Azure OpenAI's auth: entra are refused. The runtime won't start with it in development mode, or with KINDGI_WEBHOOK_PRIVATE_NETWORKS=allow or KINDGI_AUTH_PRIVATE_IDP_ORIGINS (What a tenant can't make the server do).
  • One runtime for many tenants: with KINDGI_TENANCY=multi, a runtime serves every tenant created through POST /v1/system/tenants, and takes each request's tenant from its key or session. It starts only with KINDGI_TENANT_HOST_ACCESS=isolated, per-deployment routing, OpenFGA with a key, the production gate and usage metering, and a start without any of them names each. The deployment's own token reaches only /v1/system/*. A closed tenant can still export its data for 30 days, and is then purged, and kindgi-runtime tenants repair --all sets up what an upgrade adds for each tenant (Serve many tenants).
  • Memory limits for agent turns: two new runtime settings limit the memory running agent turns hold, both off unless set: KINDGI_TURN_MEMORY_PER_TENANT_MIB for one tenant's turns, and KINDGI_TURN_MEMORY_MIB for every tenant's together. A turn is charged by size before each model call. Past either limit, the turn fails before the model is called, with 429 turn-memory-limit-reached (details.limit is tenant or server). Every tool call it finished stays in the conversation, so a new turn there doesn't call it again. A resumed run is charged its journal first, and one whose journal alone is past a limit fails with the same code. One that only finds no room yet waits: a top-level run goes back to pending, first in line, until there is room; a flow's step is left to the lease sweeper, whose third try without room fails it (about 15 minutes at the default KINDGI_RUN_LEASE_MS). The startup log shows both settings when either is set (Environment variables).
  • A failed run's details:
    • A failed run's failure can carry details when its code has them, wherever the run is read back: GET /v1/runs/{runId}, the runs list, and the answer to a POST /v1/runs that waited. For rate-limit-exceeded, details has limit (schema-compile-time or template-render-time) and budgetMs, the names the 429 uses. It never has the wait: the start's 429 gives it in Retry-After. Other codes, and runs from an older runtime, have no details.
    • A run.finished webhook's run can carry failure (code, message, cause when set, and details) beside failureMessage, which stays. It's there only when the run failed, and only from a runtime that sends it: read failureMessage when it's absent. parseEvent (@kindgi/sdk/webhooks) reads it.
    • The run stream's run.failed still carries only the message. For the code and details, read the run (GET /v1/runs/{runId}).
  • A license renewal can send the deployment's use:
    • kindgi license renew --runtime <url> --runtime-token <ref> sends the deployment's use with a non-production key's renewal: counts only (runs started, people, projects in production, and the runtime's version), with no content, names or ids. access.kindgi.com keeps and reads them from the date on its privacy page. Without the two flags, a renewal carries none, as before (Renew the license key).
    • A renewal whose counts are above what a non-production key covers is refused with held-for-review, and gets no new key until Kindgi reviews it.
    • GET /v1/license/usage?since=<time> answers those counts, for the deployment's own token or a system key holding system:license.
  • Coding agents:
    • kindgi init and kindgi skills sync write Kindgi's skills to .agents/skills/ as well as .claude/skills/. Codex and Gemini CLI read skills from .agents/skills/. Each folder holds the same copy of each skill, and kindgi skills sync checks each copy on its own: a copy you edited is kept unless you pass --force, and a folder you deleted is written again (Coding agents).
    • kindgi skills sync prints its summary on stderr, one block per folder, unless you pass --json or --quiet. In its JSON, each outcome names its folder.
    • A .prettierignore your project already has gets .agents/skills/kindgi-*/ beside .claude/skills/kindgi-*/, from kindgi init in an existing TypeScript app and from kindgi skills sync, which never creates one.
    • The templates' AGENTS.md name both folders, and say which commands are yours to run in your own terminal.
  • Kindgi Cloud, from the CLI: kindgi build --hosted, or the env block's build: 'hosted', builds your pack on Kindgi Cloud's build service. kindgi deploy --hosted builds and deploys it, then waits up to 5 minutes for its pack service to be ready. It signs with a key of yours (kindgi key create, then kindgi key trust once), named with --signing-key or the environment's signingKey.
  • The CLI waits out a rate limit: kindgi deploy, kindgi flows publish, kindgi agents publish and kindgi blocks publish wait out a 429 rate-limit-exceeded that says when to try again (Retry-After), then send the same request again, printing one line on stderr for each wait. They wait 10 minutes at most in all. Past that, on a 429 without Retry-After, or when Ctrl+C stops a wait, they fail with the error, as before. A script that runs them can take up to 10 minutes longer to fail.
  • Read a run's journal a page at a time: GET /v1/runs/:runId/journal takes limit (1 to 100) and cursor. Each page has hasMore, and nextCursor while more remain; in Python, runs.journal takes limit and cursor, and the page has has_more and next_cursor. Without limit, the whole journal comes in one answer, as before. A limit that isn't a whole number of 1 or more, or a malformed cursor, is 400 bad-input. kindgi runs journal --limit --cursor and the TypeScript client took them already; a runtime before 0.1.8 answers the whole journal (Read a run's journal).
  • Check a restore's secrets: kindgi-runtime check stored-secrets decrypts each live version of every stored secret with the runtime's keys, and names by id each one that doesn't. Run it after a restore, before the runtime serves: a restore brings back the database, not the keys (Back up and restore).
  • Capabilities for a tenant's first admin: the person a tenant is created with (firstAdmin on POST /v1/system/tenants, and whoever signs up for Kindgi Cloud) holds every capability but secrets:reveal: trusting signing keys, and writing secrets and environment values. Their sign-in sessions carry them, and the console's Create a key offers them under What it can change, so a key made there can trust signing keys and sync secrets (Who can do what).
  • Authorization on a managed Postgres:
    • With authorization on, a runtime whose database user has no BYPASSRLS (and isn't a superuser), the usual case on a managed Postgres, now starts. On 0.1.6 and 0.1.7 it didn't (Known limitations in 0.1.7).
    • A runtime that shares its database with others brings only its own tenants' authorization stores up to the current model, and drains only their changes to OpenFGA.
    • When the runtime can't read or update one tenant's part of the queue of permission changes it sends to OpenFGA, it logs an error and goes on with the other tenants. That tenant's changes apply on a later pass, with no restart (Run with authorization).
  • Guardrails scoped to flows: a guardrail whose scope lists flows now checks the turns those flows' steps start, and replays of those turns. In 0.1.7 it never checked a turn: a turn didn't say which flow it ran in, so the guardrail skipped it without a word. A halt one can now stop turns that 0.1.7 let through. A turn outside those flows is still skipped (Which agents it covers).
  • Requests:
    • An idempotency key compares request bodies byte for byte. A key limited to a project that sent one Idempotency-Key with another body now gets 409 idempotency-key-body-mismatch, and a binary upload sent with a key is stored as it was sent.
    • A key limited to a project can upload a run's artifacts. An upload that names no project goes to the key's project, and one that names another project is refused with 403 key-project-mismatch.
  • Secrets: a secret the store can't take for its name or its value is refused with a 400 and a code that says why. It was a 500 secret-store-error.
    • Under kindgi dev, a name that isn't capital letters, digits and underscores, starts with a digit, or is KINDGI_* answers secret-name-invalid, and a name starting with kindgi. answers reserved-name-prefix. That covers storing a secret, setting the tenant's configuration, and registering a webhook trigger that generates its secret, which is now refused before anything is stored.
    • Under kindgi dev, a value no env-file quoting can hold so that it reads back unchanged answers secret-value-invalid. The message doesn't repeat the value (Under kindgi dev).
    • With KINDGI_SECRETS_BACKEND=postgres, a name starting with kindgi. answers reserved-name-prefix, and a value over the store's size limit answers secret-value-too-large, as the in-memory store already did.
    • Rotating a secret in the Postgres store answers the same refusals with the same codes, and the in-memory store answers an oversized new value with secret-value-too-large.
  • kindgi dev says what stopped it: when something around it refuses what it needs, kindgi dev says what was refused and what to do, and so do kindgi doctor and kindgi auth registry for Docker.
    • A docker that can't be started (spawn docker EPERM), a Docker socket that refuses the connection, and an engine that doesn't answer each get their own message. kindgi dev no longer tries to pull the runtime image when it can't reach Docker, and no longer suggests installing Docker, or another Postgres, when Docker is there.
    • When it isn't allowed to listen on any port of 127.0.0.1 (listen EPERM), it says so, where it read every port as in use. A pack service that can't listen gets the same.
    • A file or folder it can't write (EROFS, EACCES, EPERM) is named, with the code.
    • Each of these ends with what a coding agent's sandbox needs: "If a coding agent runs this, its sandbox is likely what stops it: run kindgi dev in your own terminal instead."
    • A docker logs that can't start while the runtime starts no longer stops kindgi dev.
  • Build logs: a build's log stream that's cut before its end is opened again, and the lines it replays are printed once.
  • MCP servers: an MCP server whose outputSchema doesn't compile no longer fails its tool listing: its tools are listed, and that tool's results fail with "The server's outputSchema doesn't compile: …" (MCP servers).
  • Proposals: evaluating a proposal whose model settings aren't valid model settings is refused with 400 validation-failed, and nothing is stored.
  • Logs: a 501 answer is logged at info, not error: the runtime doesn't offer what was asked, and nothing failed. So under kindgi dev, the console's permissions read no longer prints an ERROR line. Every other answer of 500 or more stays at error (Logs).
  • The license key: the license renewer's key (kgi_lrk_…) is masked in logs, like every other Kindgi token.
  • Listing secrets:
    • kindgi secrets list --include-revoked, and includeRevoked in the clients (include_revoked in Python, which gains it), now list revoked secrets too, with their revokedAt and revokeReason, never a value. Before, the API dropped the flag.
    • The list comes in pages, by name: 25 to a page, --limit up to 100, and while more remain a nextCursor to pass as --cursor. The kindgi dev store used to stop at the first page, so a 26th secret was out of reach. A cursor the list didn't issue is 400 bad-input.
    • Names come in byte order, whatever the store or the database's collation: capital letters before lowercase ones, and - and . before letters (ORDERS, orders-db, orders.db, ordersa). A runtime on Postgres used to follow the database's own collation.
    • A secret's versions, GET /v1/secrets/:name/versions, come in pages the same way, oldest first.
    • A runtime before 0.1.8 returns only the first page of either list, with no nextCursor, and ignores --include-revoked (Store a secret).
  • Routing names a model provider the runtime can't set up: a provider registered for the tenant whose settings the deployment no longer allows used to leave only 422 capability-routing-failed, "No registered provider satisfies the capability declaration", with the reason in the runtime's log alone. Now the message names the first such provider and the setting its adapter refuses (or, when the adapter fails to build it, says the runtime's log has why), and counts the rest; the reasons list each under provider set up with the code provider-setup-failed, and GET /v1/providers/{providerId}/check gives the adapter's own words (Choose a model).
  • A tenant SSO sign-in whose identity provider's userinfo request fails (the provider can't be reached, or KINDGI_TENANT_HOST_ACCESS refuses its address) now ends at the sign-in page with sign-in-unavailable, and the runtime logs why under sso. It ended at an empty 500 page. No session is created.
  • A runtime release stops starting 90 days after it's released: from 0.1.8 until Kindgi 1.0, in every mode, unless a production key exempts it. Releases before 0.1.8 don't expire. A running server keeps running, but a platform that restarts instances on its own (Cloud Run, Container Apps) doesn't bring one back after that day. The startup banner, the console and kindgi dev warn from 30 days before, and GET /v1/license reports it as preview (Preview releases stop starting after 90 days).
  • MCP endpoints with a credential in config.headers: registering an MCP endpoint with a header whose name says it carries a credential (Authorization, X-Api-Key, …) in config.headers is refused: invalid-mcp-endpoint, reason credential-in-headers. Send it by reference instead, with auth: { scheme: "header", headers: [...] } (MCP servers). An endpoint registered that way before 0.1.8 keeps working. It reads back [redacted] for each such header, its requests never follow a redirect, and kindgi doctor warns about it.
  • Gemini through a proxy: the Gemini adapter calls Google's own host for the Developer API and for each Vertex AI location. GOOGLE_GEMINI_BASE_URL and GOOGLE_VERTEX_BASE_URL in the runtime's environment no longer move its calls. If you set either to send Gemini calls through a proxy, they now go to Google directly.
  • What Kindgi reads from the servers it calls:
    • An HTTP tool's timeoutMs, and a run's cancel, now cover reading the answer, and an answer over 10 MiB fails the call (HTTP tools).
    • Kindgi asks the servers it calls for you (MCP servers, HTTP tools, a model's base URL, your identity provider, an image registry) for answers sent uncompressed (accept-encoding: identity). An answer sent compressed anyway is refused, never decoded.
    • An answer is read up to 10 MiB. An event stream (an MCP server's) is bounded per event, so a long stream keeps going.
    • Your identity provider and an image registry have 120 s to start answering.
    • Verifying an image reads its manifest up to 4 MiB and the file it needs up to 10 MiB, and cuts a layer that sends more than its manifest declares. The deploy answers 400 image-unverifiable, its message naming the limit.
    • A layer that isn't a readable tar archive is refused, naming the archive's error: Layer … isn't a readable tar archive: TAR_ENTRY_INVALID: checksum failure, or …: TAR_BAD_ARCHIVE: Truncated input … for a file cut short, which was read cut short before.
    • A pack service's refusal is quoted up to its first 4 KiB, ending in … when there was more.
  • Request size and depth:
    • A request body over 10 MiB is refused with 413 request-too-large, whose details.maxBytes is the limit. JSON that nests objects and arrays more than 128 levels deep is refused with 400 bad-input, whose details.maxDepth is the limit. Both were accepted before. An artifact upload keeps its own size limit (413 artifact-too-large), and its body isn't read as JSON; the webhook receiver keeps its own too (413 webhook-body-too-large).
    • A signed webhook delivery whose JSON event nests more than 128 levels deep is refused the same way, and starts no run. The trigger's fires record it with detail: body-too-deep (Start runs from webhooks).
  • Schemas: a JSON schema over 1 MiB as JSON, or nested deeper than 64 levels, is refused when it's published, and nothing is stored. One stored before 0.1.8 is refused the first time it's used. That's every schema you write: a tool's input and output schemas (an MCP server's tools too, when it lists them), an agent's typed output, a flow node's output, a settings block's schema and a guardrail's config schema.
  • Guardrails: a built-in check's regular expression (must-cite's sourcePattern, output-matches' pattern) longer than 8,192 characters with its flags is refused like one that doesn't compile: registering the guardrail answers 422 guardrail-config-invalid, and deploying a pack with one fails with deployment-validation-failed. A guardrail registered before 0.1.8 with one can't run its check (Use a built-in check).
  • Prompt templates:
    • Template renders on a self-hosted server and under kindgi dev now have a memory limit: 16,777,216, in the template engine's memory units, roughly the characters of the strings the render builds and the items of its arrays. No setting changes it. A render past it fails the agent's turn with model-invocation-failed: Prompt render failed: Template render failed: the render went over its memory limit of 16777216.
    • An agent's instructions are checked as Liquid when the agent is defined, published (POST /v1/agents) or deployed. Instructions that aren't valid Liquid, or that use an unknown filter, are refused there; before, they were accepted and failed at every render. A deployment with such an agent is refused whole. To write {{ or {% as text, put it in {% raw %}…{% endraw %}.
    • A prompt block whose template uses an unknown filter is refused when it's published. Rendering it always failed.
    • Partials ({% include %}, {% render %}, {% layout %}) are refused wherever a template comes in, with "templates can't use include, render or layout". A template stored with one before 0.1.8 fails when it's rendered (render-failure), with the same message; nothing stored is changed.
  • What a project reaches:
    • A run that names a project runs only an agent or flow that project reaches. Naming one it doesn't is refused with 400 reference-out-of-scope: This project can't reference agent "<id>": it isn't registered in this project, its org or the tenant.
    • Registering an agent, flow or guardrail is refused the same way when it names a tool, agent, flow, guardrail or data block its project doesn't reach, or one that doesn't exist yet: register a guardrail before the agent that names it.
    • A guardrail names a pack check only when a guardrail of the same project names it already: a deployment brings its checks with its guardrails. Built-in checks work in every project.
    • Under kindgi dev, the echo provider's demo.echo tool is every project's, and the seeded demo.echo-agent is the Default project's: another project needs agents of its own.
    • A conversation opened before 0.1.8 in a project its agent isn't registered for can't be continued: 404 agent-not-found, The conversation was opened with agent "<id>@<v>", which is no longer registered. The runtime names such conversations when it starts.
    • An MCP endpoint's catalog tools are reached by the endpoint's scope.
    • A tool id is served as an MCP catalog tool only while every version of it that counts is one the catalog sync wrote. A version published under the same id (an HTTP tool, say) turns it off in every project until that version is unregistered; an unregistered version still counts while a flow or agent version pins it. The runtime logs mcp-tool-unroutable for such a tool: MCP tool <id>@<v> isn't served: <id> also has a version the MCP catalog sync didn't write (<versions>), so no version of it is a catalog tool. Unregister it; one a flow or agent version still pins counts until those versions are replaced. Retiring an endpoint unregisters only the versions the sync wrote.
    • A tool's metadata can't set kindgi. keys: POST /v1/tools and deploys refuse it.
  • Secrets:
    • A tool version, MCP endpoint or webhook trigger registered on 0.1.8 records where each secret it names is read. A name its record lacks is read nowhere, never at the tenant. Only an item registered before 0.1.8, with no record at all, reads at the tenant as before.
    • A webhook trigger registered on 0.1.8 reads a signing secret set for its project or its org. On 0.1.7 such a secret wasn't read, and every delivery was refused (Register the trigger).
    • A tool version whose publisher administers no scope an optional secret could be read at fails every call with secret-unavailable, as it does for a required one: tool "<id>" reads no secret "<NAME>": whoever published this version administers no scope it could be read at. A project admin publishes a new version. The call is refused before any of its secrets is read. An optional secret that simply isn't set still lets the call go on without it.
    • Unregistering a version stops it being chosen, not the pins that hold it: a flow version runs the agent version each agent step holds and the tool versions it pins, and an agent version runs the tool versions it pins. The check and the startup warning also list an unregistered tool version a flow or agent version still pins, marked (unregistered, still pinned). Its fix: publish a new tool version; for an agent that pins it, publish an agent version whose range takes the new one and make it live (kindgi agents promote); then publish a new version of each flow that pins the old tool or runs the old agent version, changing an agent step that names that version. The order matters: a flow pins each agent at its live version when the flow is published, so a flow published before the new agent version is live pins the old one again. The startup scan also warns about an unregistered agent version a flow version still runs.
  • Conversations and memory:
    • Running a turn as an end user (participantId) takes being that person, or write on the project, as reading their memory does; anyone else gets 403 participant-not-allowed. Nothing changes for existing callers: every role that can run an agent holds write.
    • With authorization on, an agent whose memory.remember.scope is 'tenant' proposes a fact for the whole tenant only in a turn whose caller, a person or a key, is a tenant admin: facts every project reads are a tenant-level decision. With anyone else the call doesn't run, and the model is told it needs a tenant admin. The other scopes are unchanged (Give an agent memory).
  • Webhooks: IPv6 site-local addresses (fec0::/10, deprecated since 2004) count as private. Outside development mode they're refused, as other private-network addresses are, unless KINDGI_WEBHOOK_PRIVATE_NETWORKS=allow, which opens them too.
  • Suspending a tenant or a project (a runtime serving many tenants):
    • A suspended tenant's or project's webhook deliveries are answered 202 with skipped: tenant-suspended or skipped: project-suspended, as a paused trigger's are, so a sender such as WooCommerce doesn't count them as failures. The event isn't kept: a sender that can resend by hand can send it again once the tenant or project is restored.
    • A closing tenant refuses webhook deliveries with 409 tenant-closing. When the tenant's state can't be read, a delivery gets 503 tenant-state-unavailable with Retry-After.
    • A schedule's or a webhook trigger's fire that a suspension stops, or whose run starts as its tenant is suspended or starts closing, is recorded skipped, with the reason in its detail. It doesn't count toward a schedule's auto-pause. A tenant's suspension isn't caught up after the restore, whatever the schedule's catchUp.
    • Suspending a tenant or a project that's already suspended keeps the first suspension's time and reason.
  • The CLI:
    • A deployment larger than the server takes in one request now says what to do: "The deployment is larger than the server takes in one request. Every tool, agent, flow and guardrail in the pack travels in it with its schemas and instructions: make the largest schemas smaller, or split the pack into two."
    • kindgi dev's banner has a Models line in place of Providers: each provider with its models or, with none yet, what agents do meanwhile and a link to Models. kindgi init's next steps say the same. kindgi doctor still names the kindgi providers register command to run.
    • A build service's refusals print plainly, with their code and the wait they ask for. A 429 with Retry-After is waited out, and the same build is sent again.
    • kindgi deploy --project checks the project before an inline build, so a project that isn't there fails before anything is built.
    • Your API key goes only to the address it's for. kindgi deploy with a stored key (the one kindgi auth login keeps, or kindgi dev's .kindgirc.json) refuses to send it to another address, wherever that address is named: --endpoint, an environment's endpoint, --url, KINDGI_API_URL or a folder's .kindgirc.json. The refusal names both addresses and how to fix it. A stored key with no address stored beside it is refused too. A key given with --token or KINDGI_API_TOKEN goes where the command says, as before. Addresses are compared after normalizing: a host's case, a scheme's default port and a trailing / don't count, and localhost, 127.0.0.1 and [::1] are one address.
    • With --hosted, or build: 'hosted', the build and the deploy go to the CLI's own API address (--url, KINDGI_API_URL, or the one you signed in to), and an environment's endpoint may only repeat it. Before, an environment's endpoint won. They don't read a .kindgirc.json that's for a kindgi dev runtime: one kindgi dev wrote (with --runtime-url too), or one at localhost, 127.0.0.1 or [::1].
    • A build that signs checks its key before building anything. With no key, it stops and says how to make one, have it trusted and name it. A key file that isn't there, or isn't a file, stops it too, naming the path and where it was set.
    • kindgi init's TypeScript templates leave environments empty, with a commented Kindgi Cloud block and a commented block for a runtime of your own. Before, a new pack carried placeholder environments that a deploy would use.
    • kindgi deploy --project <slug> with no such project points to kindgi projects list. It named a command that doesn't exist.
    • kindgi adapters prepare --params reads its JSON from a file with @<file>, as its usage line said and as every other such flag does. JSON that doesn't parse is a usage error (exit 2), and nothing is sent.
    • Four commands' help now says what they do. kindgi dev --tenant: with the bundled Postgres, the default tenant is the project's own, the same for every pack and restart; otherwise it's the last run's, from .kindgirc.json, else a new one. kindgi build --signer-key-id: the default is the environment's signerKeyId, else the key file's name. kindgi sso providers start: --kind is optional, and comes from --idp, else from the registered provider. kindgi schedules update: a flag left out keeps the schedule's value.
    • kindgi artifacts upload --help, the API's description of POST /v1/artifacts and the clients' docs give the default upload cap as 100 MiB, what it always was (100 * 1024 * 1024 bytes). They said 100 MB.
  • The license key's signing key: the runtime and the CLI trust a new production signing key, so a production key issued after 0.1.8 can need runtime 0.1.8 or later. Kindgi tells you which runtime a key needs when it issues it, and a licensee on an older runtime keeps getting keys their runtime verifies.
  • Logs:
    • KINDGI_LOG_LEVELS now warns at boot for auth and db: nothing logs under them, so a level set for either never had an effect. Levels for judging, migrations, sso and tenants always applied, and no longer warn that they don't.
    • Records from aws-identity and openfga now carry their own subsystem, where they said root, so a level for either applies too.
    • The scheduler's lines are now records under schedules: each fire, with its outcome and the run or improvement pass it started; a trigger paused; what a restore skipped; and failures. So are the improvement-passes warning that passes couldn't resume, and the authz.outbox warnings a request printed while it waited for its access changes to apply. They follow KINDGI_LOG_LEVELS and KINDGI_LOG_FORMAT: under JSON each is one object on its own line, where it used to break the stream (The subsystems).
  • A first admin who stops being a tenant admin loses their capabilities, and being made one again doesn't return them. Keys that carry them make new keys with them, so replace the last one before it goes. With neither, contact support (Make someone a tenant admin).
  • Run one runtime instance. Several instances sharing a database aren't verified on a platform yet, so the Cloud Run module still runs one (Cloud Run).
  • A secret hard-revoked before 0.1.8 in your own secret manager (KINDGI_SECRETS_BACKEND=secret-manager) lists under kindgi secrets list --include-revoked as a revoked secret: its name, revokedAt and revokeReason, never a value. The runtime kept nothing then that told a hard revoke from a soft one. A secret hard-revoked from 0.1.8 on is left out of every list.
  • With a key for OpenFGA (KINDGI_OPENFGA_PRESHARED_KEY), kindgi-runtime tenants purge and tenants repurge stop at a tenant with an OpenFGA store: they don't send the key, or the ID token behind Cloud Run IAM, so the store's delete is refused, and they exit 2 with OpenFGA answered <status> to deleting store <id>. By then the tenant's artifacts' bytes are deleted, but none of its rows. A repurge stops there, before the records after it. Fixed in 0.1.8.1, the next release: once you've upgraded to it, run the purge again (Close and purge a tenant).
  1. Before you upgrade, list the MCP endpoints with a credential in config.headers, with the 0.1.8 image's check mcp-header-credentials (Operate). They keep working, but move each one: store each header's value as a secret, then unregister the endpoint and register it again with the header in auth (MCP servers).
  2. Before you upgrade, list what reads a secret at the tenant from a project or an org, with the 0.1.8 image's check secret-scopes (Operate). They were registered before 0.1.8 and keep reading at the tenant. One a tenant admin registered can stay. The check ends with what to do about the others: register each again, a webhook trigger with kindgi webhooks update <trigger-id> --secret=<name>.
  3. If a server Kindgi calls compresses its answers whatever the request asks, turn that off before you upgrade: 0.1.8 refuses a compressed answer.
  4. Check that your agents' instructions are valid Liquid. A deployment with an agent whose instructions aren't is refused whole, so a CI deploy that passed on 0.1.7 can fail on 0.1.8.
  5. Expect a slower first start on a large database. Two new indexes on the runs table are built at the first start after the upgrade, without blocking writes; the more runs, the longer that start takes.
  6. After you upgrade, read the startup log for conversations that can't be continued (opened before 0.1.8 in a project their agent isn't registered for) and for unregistered versions a flow or agent version still pins: the runtime names each.
  7. If a deploy sends the key kindgi auth login or kindgi dev stored to another address, give it that server's key with --token or KINDGI_API_TOKEN, point the address at the one stored with the key, or, for a key from kindgi auth login, sign in to that server with kindgi auth login --url <url>. The 0.1.8 CLI refuses to send a stored key anywhere else, and the refusal names the setting that names the other address.