KLKLine FrontendDashboard · Preview · Embed shell

Admin widget builder

Persisted save DTO and error contract

F033 freezes the create/update DTO and typed error mapping while direct persistence remains dry-run and fail-closed.

DTO mode

create/update

Create and update share one JSON-safe envelope.

dryRun

TRUE

The frozen DTO is still not a live mutation call.

Save disabled assert

PASS

The helper rejects non-dry-run or token-like requests.

Errors

5

Stable frontend error codes are mapped before UI wiring.
F033 · DTO/error contract freeze

Persisted save DTO and typed error contract

This freezes the request/response/error shape that future F037 can use behind a feature flag. It does not call `POST /api/admin/widget-instances` or `PATCH /api/admin/widget-instances/:id`.

Create request envelope
{
  "schemaVersion": "kline.admin-widget-config.v1",
  "mode": "create",
  "draft": {
    "widgetType": "advanced-kline-chart",
    "config": {
      "widgetId": "demo-advanced-kline",
      "widgetType": "advanced-kline-chart",
      "publicKey": "pk_demo_local_only",
      "symbol": {
        "id": "BINANCE:BTCUSDT",
        "ticker": "BINANCE:BTCUSDT",
        "displayName": "Bitcoin / Tether",
        "exchange": "BINANCE",
        "provider": "binance-public-demo",
        "pricePrecision": 2,
        "volumePrecision": 6,
        "currency": "USDT",
        "timezone": "UTC"
      },
      "interval": "1h",
      "allowedIntervals": [
        "1m",
        "5m",
        "15m",
        "30m",
        "1h",
        "4h",
        "1d"
      ],
      "theme": "dark",
      "locale": "fa",
      "features": {
        "toolbar": true,
        "indicators": true,
        "drawings": true,
        "realtime": true,
        "snapshot": true,
        "objectTree": true
      }
    },
    "chartStyle": "candle",
    "appliedAt": 1784097188367
  },
  "parentContainer": {
    "width": 1180,
    "minHeight": 620,
    "height": 620,
    "display": "block"
  },
  "idempotencyKey": "kline_create_am08a2",
  "dryRun": true,
  "requestedAt": 1784097188367
}
Update request envelope
{
  "schemaVersion": "kline.admin-widget-config.v1",
  "mode": "update",
  "draft": {
    "widgetType": "advanced-kline-chart",
    "config": {
      "widgetId": "demo-advanced-kline",
      "widgetType": "advanced-kline-chart",
      "publicKey": "pk_demo_local_only",
      "symbol": {
        "id": "BINANCE:BTCUSDT",
        "ticker": "BINANCE:BTCUSDT",
        "displayName": "Bitcoin / Tether",
        "exchange": "BINANCE",
        "provider": "binance-public-demo",
        "pricePrecision": 2,
        "volumePrecision": 6,
        "currency": "USDT",
        "timezone": "UTC"
      },
      "interval": "1h",
      "allowedIntervals": [
        "1m",
        "5m",
        "15m",
        "30m",
        "1h",
        "4h",
        "1d"
      ],
      "theme": "dark",
      "locale": "fa",
      "features": {
        "toolbar": true,
        "indicators": true,
        "drawings": true,
        "realtime": true,
        "snapshot": true,
        "objectTree": true
      }
    },
    "chartStyle": "candle",
    "appliedAt": 1784097188367
  },
  "widgetInstanceId": "00000000-0000-4000-8000-000000000031",
  "parentContainer": {
    "width": 1180,
    "minHeight": 620,
    "height": 620,
    "display": "block"
  },
  "expectedRevision": 3,
  "idempotencyKey": "kline_update_47fw0n",
  "dryRun": true,
  "requestedAt": 1784097188367
}
Error mapping matrix

HTTP 401

ADMIN_UNAUTHENTICATED

missing admin session

HTTP 403

WIDGET_TENANT_MISMATCH

tenant mismatch

HTTP 409

WIDGET_SAVE_CONFLICT

revision conflict

HTTP 422

WIDGET_CONFIG_INVALID

invalid widget config

HTTP n/a

WIDGET_SAVE_NOT_ENABLED

network unavailable