Skip to content

ctx v4.0.0-rc1

Choose a tag to compare

@github-actions github-actions released this 27 Jun 23:20
· 1250 commits to root since this release
v4.0.0-rc1
52b99b0

v4.0.0-rc1 — Multi-tenant: scope is the tenant boundary

Release candidate for v4.0.0 (the multi-tenant major). Promoted to the final
v4.0.0 tag once CI and the release build are green on root. The notes below are
the v4.0.0 release notes.

The store goes multi-tenant on the Modell-C architecture — three nesting levels
(tenant ▸ scope ▸ block), with scope as the partition discriminator and NO
tenant_id on any data table. A single-tenant deployment stays byte-identical:
the default tenant owns the existing scopes, so every path behaves exactly as on
v3 until real tenants are provisioned. Built across seven axes / ~34 waves, each
TDD (red→green) + adversarially mutation-verified, on the feat/multi-tenant line
(migrations 058–068; the optional 066, tenant-owned OAuth, is deferred).

BREAKING:

  • Migration 058 drops the legacy 3-value scope CHECK; scope is now
    VARCHAR(50), unconstrained at the schema level — the data-table discriminator
    for arbitrary tenant scopes.
  • api-key-list now defaults to ACTIVE keys only; soft-deleted keys need an
    explicit active_only=false (audit/forensics tooling must send it; design/05
    §6.2).
  • Freshly minted foreign-tenant keys no longer inherit shared implicitly
    (R-LEAK5) — only the default tenant auto-inherits it.

What's new:

  • Tenant register + lifecycle (059/060): context_tenants, per-request ctx_auth
    with a status gate (suspended/offboarding ⇒ UNAUTHORIZED, fail-closed) and
    positional read_scopes; a full FK-ordered tenant prune (no orphaned blocks).
  • Fail-closed read contract: RequireScopes — an empty resolved scope set is an
    error, never a silent "all scopes" — wired into every scope-filtered store read
    and the four MCP handlers (L7).
  • Admin tier (Achse 05): typed server-admin / tenant-admin / member roles, a
    two-tier action gate, and tenant-gated key mint/list/delete (L1/L2/L3).
  • Cross-tenant read channel (061) + block-level grants (067/068, the third
    level): scope grants and per-block grants, both opt-in and least-privilege,
    behind a mandatory-parenthesised visibility OR that can't leak archived /
    system-meta blocks, graph-bridge leaf protection, and a grant-fixed egress
    sensitivity floor (config-independent personal backstop).
  • Egress isolation: a tenant-filtered backend Chain (R-LEAK7) — a tenant can
    never route a prompt to another tenant's external backend.
  • Per-tenant settings/secrets (two-write-worlds; strict-isolation secret
    fallback gated on an opt-in), a per-tenant config overlay (lazy, gen-stamped,
    single-flight) with scope-carried lazy cache invalidation (065).
  • Per-tenant cost/call quota (063) + management CLI; per-tenant telemetry
    (llmlog/status) pull views; the background pipeline iterated per tenant with
    its read window clamped to read_scopes ∩ entitlements.

Gate: the full integration suite (every package, the whole 058–068 migration
chain, the race detector) is green; a code-level pre-release isolation audit found
no cross-tenant leak across the read/write, settings/secrets, admin-tier, MCP, chat
and background paths. Three deliberately deferred seams (tenant-owned OAuth, the
dream round-robin's scope-blind PickBlock, the global quota default) are documented
and carry no leak. Rollout to a running deployment (migrating the production DB from
057 across the chain) is a separate operational step.

Installation

With Go:

go install github.com/GottZ/ctx/cmd/ctx@v4.0.0-rc1

Binary download:
Download the binary for your platform, make it executable, move to PATH:

chmod +x ctx-*
sudo mv ctx-* /usr/local/bin/ctx