---
id: w7/m5/t003
title: Surface ipAllowList on Key Value create/update + read-back across REST · GraphQL · MCP
worker: worker7
status: done
estimate: 45m
depends_on: [w7/m5/t002]
---

## Objective

Expose the new `ipAllowList` field on all three programmatic Key Value surfaces — settable on create and update, readable back — so an agent (and the dashboard) can manage the allowlist the same way it manages other KeyValue fields. Match the field name/shape Render uses and the shape managed Postgres already uses on bex.

## Context

- `lego/backend/internal/keyvalue/{rest,graphql,mcp}.go` — the three KeyValue adapters over the one core. Render's KV MCP set is intentionally the 3-tool `list/get/create` subset (delete/suspend are REST+GraphQL only) — keep that asymmetry; add `ipAllowList` to `create` (all three) and to update where update exists.
- Compare with the managed-Postgres allowlist surfacing for field name (`ipAllowList`) and `[]string` shape.

## Steps

1. Thread `ipAllowList` through the KeyValue core create/update path into `spec.ipAllowList`.
2. REST: accept + return `ipAllowList` on the KV create/update/get bodies.
3. GraphQL: add `ipAllowList` to the KeyValue type + `createKeyValue`/update input.
4. MCP: add `ipAllowList` to `create_key_value` (and any update tool if present).
5. `cd lego/backend && go build ./... && go test ./...`.

## Files

- `lego/backend/internal/keyvalue/rest.go`
- `lego/backend/internal/keyvalue/graphql.go`
- `lego/backend/internal/keyvalue/mcp.go`
- (core) the KeyValue create/update handler these adapters share

## Acceptance criteria

- [ ] `ipAllowList` is settable on create and readable back on REST, GraphQL, and MCP; settable on update wherever update exists.
- [ ] The field name/shape matches Render's `ipAllowList` and bex's Postgres field; MCP keeps Render's 3-tool KV subset.

## Out of scope

- Dashboard UI (t004); cross-surface parity audit (t005).
