Persist deployment-page monitoring fields end-to-end (payload size/unit, metrics interval, replay, route control) #148

Open
opened 2026-04-22 23:47:44 +02:00 by claude · 0 comments
Owner

Context

Surfaced during manual QA of the unified app deployment page (spec: docs/superpowers/specs/2026-04-22-app-deployment-page-design.md, plan: docs/superpowers/plans/2026-04-22-app-deployment-page.md).

The Monitoring tab on /apps/:slug renders five controls that the old CreateAppView also rendered but never persisted:

  • Max Payload Size — numeric input + unit select (B / KB / MB)
  • Metrics Interval — integer seconds, inline with the Metrics toggle
  • Replay — enable/disable agent replay
  • Route Control — enable/disable route start/stop commands

These are currently UI-only: they mount with sensible defaults (payloadSize='4', payloadUnit='KB', metricsInterval='60', replayEnabled=true, routeControlEnabled=true) but are not written to the ApplicationConfig DTO on Save and are not read back on load. The Java com.cameleer.common.model.ApplicationConfig model does not carry these fields, and the agent SSE protocol does not consume them. The pre-existing CreateAppView had the same gap — we are not regressing prior behavior, only surfacing it.

The user has stated these controls must be configurable during deployment and must affect agent behavior. Fixing this requires coordinated work across this server and the agent repo.

Scope

1. cameleer-common (shared model)

Add the five fields to ApplicationConfig:

Integer payloadCaptureMaxSize;   // bytes, computed from UI (size, unit) pair
Integer metricsIntervalSeconds;
Boolean replayEnabled;
Boolean routeControlEnabled;

Recommend collapsing payloadSize + payloadUnit into a single bytes integer on the wire — the UI already does the unit conversion in the old code. Keep the UI as two inputs; serialize as one.

Consider whether payloadCaptureMaxSize needs a null default (meaning "use agent-side default") or a hard default. Existing field style (e.g. samplingRate always has a value) suggests hard defaults — document them in PROTOCOL.md.

2. cameleer-server (this repo)

  • Bump protocol version if the agent's handling changes require it (check X-Cameleer-Protocol-Version semantics — we're currently on 1).
  • Update ApplicationConfigController.defaultConfig to seed the new fields.
  • Add the fields to the deployed_config_snapshot JSONB via the existing DeploymentConfigSnapshot record — these should participate in dirty detection. (DirtyStateCalculator already diffs agent config, so this is automatic once the fields are on ApplicationConfig.)
  • Integration test: GET → PUT → GET round-trips the 5 fields; snapshot captures them; dirty-state detects changes to any of the 5.

3. cameleer-server UI

Wire the existing UI form state to the ApplicationConfig body:

  • ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts — read from agentConfig instead of using UI-only defaults.
  • ui/src/pages/AppsTab/AppDeploymentPage/index.tsx — in handleSave, send payloadCaptureMaxSize, metricsIntervalSeconds, replayEnabled, routeControlEnabled.
  • Regenerate OpenAPI + schema.d.ts after backend changes.

4. cameleer (agent repo)

  • Update ApplicationConfig parsing on the agent side.
  • Wire fields to actual agent behavior:
    • payloadCaptureMaxSize — already exists? If yes, read from config. If not, add to payload capture code path.
    • metricsIntervalSeconds — scheduler interval for the metrics reporter.
    • replayEnabled — gate the replay command handler (reject REPLAY commands when disabled).
    • routeControlEnabled — gate the route start/stop command handlers.
  • Update PROTOCOL.md.
  • Add agent-side tests for each gate.

5. Migration / compatibility

Existing deployed apps have no values for these fields. On first config read, the server should inject defaults into the response so the UI always shows something. Existing agents running protocol v1 without these fields should keep working (fields are additive and nullable on the wire).

Acceptance criteria

  • On /apps/new, each of the 5 controls round-trips: enter a value, Save, navigate away, come back — the value persists.
  • Deploy with replayEnabled=false → attempt a replay command → agent rejects it.
  • Deploy with routeControlEnabled=false → attempt route start/stop → agent rejects it.
  • Deploy with metricsIntervalSeconds=30 → verify the agent emits metrics every ~30s.
  • Deploy with payloadCaptureMaxSize=1024 → verify payloads over 1 KiB are truncated.
  • Changing any of the 5 fields flips the deployment page's primary button to Redeploy.

Not in scope

  • Per-route overrides for these fields (only global per-app).
  • Exposing these as admin-level defaults on the Environment.

References

  • Manual QA transcript: screenshot showed these 5 controls present in the old Monitoring layout.
  • ui/src/pages/AppsTab/AppDeploymentPage/ConfigTabs/MonitoringTab.tsx — current (UI-only) implementation.
  • ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts — where the five fields currently live as client-only state.
  • Related deferral: issue #147 (concurrent-edit protection).
## Context Surfaced during manual QA of the unified app deployment page (spec: `docs/superpowers/specs/2026-04-22-app-deployment-page-design.md`, plan: `docs/superpowers/plans/2026-04-22-app-deployment-page.md`). The Monitoring tab on `/apps/:slug` renders five controls that the old `CreateAppView` also rendered but never persisted: - **Max Payload Size** — numeric input + unit select (B / KB / MB) - **Metrics Interval** — integer seconds, inline with the Metrics toggle - **Replay** — enable/disable agent replay - **Route Control** — enable/disable route start/stop commands These are currently UI-only: they mount with sensible defaults (`payloadSize='4'`, `payloadUnit='KB'`, `metricsInterval='60'`, `replayEnabled=true`, `routeControlEnabled=true`) but are **not** written to the `ApplicationConfig` DTO on Save and are **not** read back on load. The Java `com.cameleer.common.model.ApplicationConfig` model does not carry these fields, and the agent SSE protocol does not consume them. The pre-existing `CreateAppView` had the same gap — we are not regressing prior behavior, only surfacing it. The user has stated these controls must be configurable during deployment and must affect agent behavior. Fixing this requires coordinated work across this server and the agent repo. ## Scope ### 1. `cameleer-common` (shared model) Add the five fields to `ApplicationConfig`: ```java Integer payloadCaptureMaxSize; // bytes, computed from UI (size, unit) pair Integer metricsIntervalSeconds; Boolean replayEnabled; Boolean routeControlEnabled; ``` Recommend collapsing `payloadSize` + `payloadUnit` into a single bytes integer on the wire — the UI already does the unit conversion in the old code. Keep the UI as two inputs; serialize as one. Consider whether `payloadCaptureMaxSize` needs a `null` default (meaning "use agent-side default") or a hard default. Existing field style (e.g. `samplingRate` always has a value) suggests hard defaults — document them in `PROTOCOL.md`. ### 2. `cameleer-server` (this repo) - Bump protocol version if the agent's handling changes require it (check `X-Cameleer-Protocol-Version` semantics — we're currently on `1`). - Update `ApplicationConfigController.defaultConfig` to seed the new fields. - Add the fields to the `deployed_config_snapshot` JSONB via the existing `DeploymentConfigSnapshot` record — these should participate in dirty detection. (`DirtyStateCalculator` already diffs agent config, so this is automatic once the fields are on `ApplicationConfig`.) - Integration test: `GET → PUT → GET` round-trips the 5 fields; snapshot captures them; dirty-state detects changes to any of the 5. ### 3. `cameleer-server` UI Wire the existing UI form state to the ApplicationConfig body: - `ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts` — read from `agentConfig` instead of using UI-only defaults. - `ui/src/pages/AppsTab/AppDeploymentPage/index.tsx` — in `handleSave`, send `payloadCaptureMaxSize`, `metricsIntervalSeconds`, `replayEnabled`, `routeControlEnabled`. - Regenerate OpenAPI + `schema.d.ts` after backend changes. ### 4. `cameleer` (agent repo) - Update `ApplicationConfig` parsing on the agent side. - Wire fields to actual agent behavior: - `payloadCaptureMaxSize` — already exists? If yes, read from config. If not, add to payload capture code path. - `metricsIntervalSeconds` — scheduler interval for the metrics reporter. - `replayEnabled` — gate the replay command handler (reject `REPLAY` commands when disabled). - `routeControlEnabled` — gate the route start/stop command handlers. - Update `PROTOCOL.md`. - Add agent-side tests for each gate. ### 5. Migration / compatibility Existing deployed apps have no values for these fields. On first config read, the server should inject defaults into the response so the UI always shows something. Existing agents running protocol v1 without these fields should keep working (fields are additive and nullable on the wire). ## Acceptance criteria - On `/apps/new`, each of the 5 controls round-trips: enter a value, Save, navigate away, come back — the value persists. - Deploy with `replayEnabled=false` → attempt a replay command → agent rejects it. - Deploy with `routeControlEnabled=false` → attempt route start/stop → agent rejects it. - Deploy with `metricsIntervalSeconds=30` → verify the agent emits metrics every ~30s. - Deploy with `payloadCaptureMaxSize=1024` → verify payloads over 1 KiB are truncated. - Changing any of the 5 fields flips the deployment page's primary button to `Redeploy`. ## Not in scope - Per-route overrides for these fields (only global per-app). - Exposing these as admin-level defaults on the Environment. ## References - Manual QA transcript: screenshot showed these 5 controls present in the old Monitoring layout. - `ui/src/pages/AppsTab/AppDeploymentPage/ConfigTabs/MonitoringTab.tsx` — current (UI-only) implementation. - `ui/src/pages/AppsTab/AppDeploymentPage/hooks/useDeploymentPageState.ts` — where the five fields currently live as client-only state. - Related deferral: issue #147 (concurrent-edit protection).
Sign in to join this conversation.