Skip to content

Make AI work again on hosted Void Cloud: publish AI logging policy to KV - #814

Open
Brooooooklyn wants to merge 7 commits into
mainfrom
ai-logging/proxy-kv
Open

Brooooooklyn wants to merge 7 commits into
mainfrom
ai-logging/proxy-kv

Conversation

@Brooooooklyn

@Brooooooklyn Brooooooklyn commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Since 1.8.0 the proxy asked the API for each project's AI logging policy
on every AI call, and the API refused unless PLATFORM_AUTH_DATABASE_UNCACHED
was set. Hosted Void Cloud never sets it, so every hosted AI call failed
with 503 ai_logging_policy_unavailable.

Now the API and the installer write the policy to ROUTING KV key
ai-logging:<projectId>, and the proxy reads it from there.

How AI logging works

The setting. Each project gets one AI Gateway logging mode:

Mode What AI Gateway stores
inherit Whatever the gateway is set to; Void sends nothing (same as 1.7.0)
off No log entry
metadata A log entry without the request or response bodies
full A log entry with the bodies

Which mode wins: the project's own setting, then its plan's default, then the gateway. An account on a plan that isn't in the catalog uses the default plan's setting.

Data flow

 operator / CLI / dashboard
   project ai-logging · plans set · user plan · transfer · create · delete
            │
            ▼
 ┌──────────────────────┐   lock project row, read inputs     ┌──────────────┐
 │         API          │ ──────── through a write ─────────▶ │   Postgres   │  saved settings
 │ works out the mode   │◀───────────────────────────────────── │              │  (the truth)
 └──────────┬───────────┘                                      └──────────────┘
            │ write under the lock (retries a 429 after 1/2/4 s)
            ▼
   ROUTING KV   ai-logging:<projectId> = off | metadata | full    (no key = inherit)
            ▲   metadata {mode, at}
            │ read on every AI call, 30 s cache
 ┌──────────┴───────────┐
 │        proxy         │ ──▶ AI Gateway headers for /ai/run, /ai/toMarkdown, /ai/provider
 └──────────────────────┘

The proxy no longer calls the API. That call was the 503 that broke AI on hosted Void Cloud.

Who writes the key

Event What happens
Operator sets a project mode Stricter change (e.g. full → off): one transaction, rolled back if KV fails. Looser change or inherit: saved first, then published.
Plan default changes Published 100 projects per call. plans sync continues, and the CLI keeps syncing until done.
User's plan changes One page per call; running the same change again continues it
Project create / transfer / delete Key written inside the create; republished on transfer; removed only after the row is gone
Install / upgrade / repair The installer copies every saved setting to KV, before and after the Worker upload
Every hour The sweep repairs keys that differ from Postgres (at most 400 KV operations per run)

Timing

KV reads are cached for 30 s at each Cloudflare location, so a change can take a short while to reach every location. After a change, the CLI prints "expected by HH:MM:SS (normally within 2 minutes)".

Readback

void platform project show and project ai-logging report a state:

applied               KV matches and the settle time has passed
pending               just published; some locations may still use the old value
pending_plan_publish  a plan or user-plan publish has not reached this project yet
drift                 KV differs from the saved setting (the hourly sweep fixes it)
unknown               KV could not be read

When something fails, the proxy refuses instead of guessing

  • KV read error: 503 ai_logging_policy_unavailable, with Retry-After
  • Unknown value in KV: 503 ai_logging_policy_invalid (the value itself is never logged)
  • Publish failure on a change: ai_logging_publish_failed (nothing changed) or ai_logging_publish_pending (saved, KV catches up)

Older proxies

Proxies still on 1.8.x keep calling GET /internal/ai-logging/:id. That route still exists and now answers from the same KV key, so they work during the upgrade.

Changes

Shared (@void/platform/ai-logging)

  • Key names, value and metadata shape, parsers, resolver and the 30 s
    read cache time, used by the API, the installer and the proxy.

Proxy

  • Reads the key (cacheTtl 30) in /ai/run, /ai/provider and /ai/toMarkdown,
    after body validation. Missing key: inherit (no logging option, as in
    1.7.0). off / metadata / full: the 1.8.0 gateway mapping. KV error:
    503 ai_logging_policy_unavailable. Bad value: 503
    ai_logging_policy_invalid. Caller-supplied logging keys are still
    stripped.

API

  • publishProjectAiLogging locks the project row, reads every input through
    a write statement (cached Hyperdrive reads never feed a publish), and
    writes KV before the lock is released.
  • The operator POST orders the write by direction: a tighten writes in the
    same transaction; a loosen or inherit commits first and publishes in a
    second locked step. Errors: ai_logging_publish_failed / _pending.
  • Plan defaults in platform_settings 'plans:ai-logging', published in
    pages of 100. A user plan change publishes one page per call; transfer,
    create and delete keep the key in step.
  • An unfinished plan publish follows its accounts through a catalog
    change: a removed plan's scope moves to its replacement, and a run that
    covered unknown plans also covers plans added to the catalog.
  • Readback returns saved, plan, effective, source, published and a state:
    applied, pending, pending_plan_publish, drift or unknown.
  • An hourly sweep repairs drifted keys within a 400 KV operation budget.
  • The internal route 1.8.x proxies call is kept and answers from KV.

Installer and CLI

  • Every install, upgrade and repair copies each project's setting from
    Postgres to KV, before and after the Worker upload, under the same row
    locks as the API.
  • void platform project ai-logging and project show print the source,
    effective mode and state; plan files accept aiLogging.

Docs

  • CLI reference, admin guides, upgrade note, design doc 0094, operations
    notes for the hosted rollout.

Refs #793.

Replaces the stack #814–#817 (now one PR, so the proxy switch and the KV writers land together).

Verification

🤖 Generated with Claude Code

@Brooooooklyn
Brooooooklyn requested a review from a team as a code owner November 13, 2026 13:10
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-13T14:29:23.949247Z a34adb6 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 25db0c80ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Since 1.8.0 the proxy asked the API for each project's AI logging policy
on every AI call, and the API refused unless PLATFORM_AUTH_DATABASE_UNCACHED
was set. Hosted Void Cloud never sets it, so every hosted AI call failed
with 503 ai_logging_policy_unavailable.

Now the API and the installer write the policy to ROUTING KV key
`ai-logging:<projectId>`, and the proxy reads it from there.

Shared (`@void/platform/ai-logging`)
- Key names, value and metadata shape, parsers, resolver and the 30 s
  read cache time, used by the API, the installer and the proxy.

Proxy
- Reads the key (cacheTtl 30) in /ai/run, /ai/provider and /ai/toMarkdown,
  after body validation. Missing key: inherit (no logging option, as in
  1.7.0). off / metadata / full: the 1.8.0 gateway mapping. KV error:
  503 ai_logging_policy_unavailable. Bad value: 503
  ai_logging_policy_invalid. Caller-supplied logging keys are still
  stripped.
- Adds a manual live-check script for the two Cloudflare behaviours the
  mapping depends on.

API
- publishProjectAiLogging locks the project row, reads every input through
  a write statement (cached Hyperdrive reads never feed a publish), and
  writes KV before the lock is released.
- The operator POST orders the write by direction: a tighten writes in the
  same transaction; a loosen or inherit commits first and publishes in a
  second locked step. Errors: ai_logging_publish_failed / _pending.
- Plan defaults in platform_settings 'plans:ai-logging', published in
  pages of 100. A user plan change publishes one page per call; transfer,
  create and delete keep the key in step.
- Readback returns saved, plan, effective, source, published and a state:
  applied, pending, pending_plan_publish, drift or unknown.
- An hourly sweep repairs drifted keys within a 400 KV operation budget.
- The internal route 1.8.x proxies call is kept and answers from KV.

Installer and CLI
- Every install, upgrade and repair copies each project's setting from
  Postgres to KV, before and after the Worker upload, under the same row
  locks as the API.
- `void platform project ai-logging` and `project show` print the source,
  effective mode and state; plan files accept `aiLogging`.

Docs
- CLI reference, admin guides, upgrade note, design doc 0094, operations
  notes for the hosted rollout.

Refs #793.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Brooooooklyn
Brooooooklyn removed this pull request from stack #818 November 13, 2026 13:22
@Brooooooklyn Brooooooklyn changed the title Read the AI logging policy from ROUTING KV in the proxy Make AI work again on hosted Void Cloud: publish AI logging policy to KV Nov 13, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://ai-logging-proxy-kv-void-cloud.voidzero-docs.workers.dev (commit a34adb6)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://ec6c9a93-void-cloud.voidzero-docs.workers.dev a34adb6 2026-11-13T14:27:27.347Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://02d5af95-void-cloud.voidzero-docs.workers.dev 7b5c2b8 2026-11-13T14:22:37.224Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://2b2a9dec-void-cloud.voidzero-docs.workers.dev cb29702 2026-11-13T14:15:33.965Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://fbe87071-void-cloud.voidzero-docs.workers.dev b917a38 2026-11-13T13:24:14.015Z Visit the dashboard ↗

Brooooooklyn and others added 3 commits November 13, 2026 22:09
The PR's tests checked many rules at several layers. Each rule is now
tested where it lives (shared parser, API state and plan-edit units, CLI
output, proxy mapping), and higher layers check only the wiring once.

- Shared helpers for the API integration tests (operator calls, KV
  cleanup, failing or recording KV writes, the no-cacheable-read check)
  replace up to seven copies of each.
- Removed integration tests that repeat unit-tested rules: plan edit
  rules, readback state variants, publish order rows, the key name, and
  the CLI JSON, help and plan-file mode checks that the generic tests
  and shared parser cover.
- Merged tests that ran the same path: ownership transfer, project
  create, the 1.8.x route, the default-plan lookup, the sweep's drift
  and plan-page cases, the 429 retries.
- Proxy tables keep one case per behaviour; the e2e test keeps the
  CLI -> API -> KV -> proxy path and drops output checks unit tested
  elsewhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kept route is still exercised by operator-tenants and
platform-access-protection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live checks A and B stay in design doc 0094 as manual checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb29702b3c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Removing a plan while its AI logging publish was unfinished kept the
removed plan ID in the merged run. Its accounts had moved to the
replacement, so later pages found nothing and reported the publish
complete, leaving the rest of those projects on their old setting until
the hourly sweep. This happened when both plans share a default, since
the removal then changes no account's mode.

The fold now maps the removed plan to its replacement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b5c2b8612

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Brooooooklyn and others added 2 commits November 13, 2026 22:25
…lish

A running plan publish that covered unknown plans lost the accounts on a
plan ID once that ID was added to the catalog: they no longer count as
unknown, and the add changes no mode when the new plan copies the
default. Later pages reported completion while those projects kept
their old setting until the hourly sweep.

The fold now adds plans new to the catalog when the unfinished run
covered unknown plans, next to mapping a removed plan to its
replacement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant