# Template / Scene Binding Refactor Design

## Goal

Refactor the configuration model across the admin backend and the OrangePi media service so that:

- `识别模板` only defines a single-stream processing flow and its default technical parameters.
- `基础配置` owns reusable concrete instances such as `视频源` and `第三方服务`.
- `场景配置` becomes the single assembly layer that binds template slots to concrete instances and scene-level output parameters.
- The agent runtime config format stays stable in the first phase; the main change is in the modeling and render pipeline.

This is a cross-repo refactor involving:

- `C:/Users/Tellme/apps/3588AdminBackend`
- `C:/Users/Tellme/apps/OrangePi3588Media`

## Problem Statement

The current template JSON mixes three different concerns:

1. Flow definition
2. Scene instance parameters
3. Concrete third-party service endpoints and credentials

That creates several problems:

- Templates are not reusable enough because they carry site-specific and service-specific values.
- Service endpoints and credentials are duplicated in templates instead of being centrally managed.
- Scene configuration is not the true assembly layer even though it is the closest object to actual deployment.
- The same conceptual binding is split between template params, profile params, and runtime substitution.

The target model should separate these concerns cleanly.

## Target Information Architecture

### 1. 识别模板

Template is a reusable processing definition for **one video stream**.

Template owns:

- Node graph
- Edge graph
- Default algorithm parameters
- Default preprocess and publish technical parameters
- Declarations of required input / output / service slots

Template does **not** own:

- Concrete video source URLs
- Concrete third-party service instances
- Scene-specific publish paths or ports
- Site-specific display labels

### 2. 基础配置

Base config owns reusable concrete instances.

Initial scope:

- `视频源`
- `第三方服务`

These objects are real instances that can be shared by many scenes.

### 3. 场景配置

Scene config is the only assembly layer.

It owns:

- Template selection
- Binding of template input slots to video-source instances
- Binding of template service slots to third-party service instances
- Binding of template output slots to scene-specific publish settings
- Scene-level labels and business parameters

## Data Model Boundaries

### Template-owned fields

These remain inside template definitions:

- Node types
- Edges
- Model paths
- Thresholds
- Inference rates
- Preprocess defaults
- Publish codec defaults
- Alarm rule structure
- Default sink behavior

Examples from existing templates:

- `infer_fps`
- `conf_thresh`
- `nms_thresh`
- `dst_w`
- `dst_h`
- `codec`
- `bitrate_kbps`
- `rules`
- `face_rules`

### Scene-owned fields

These move to scene config:

- `publish_hls_path`
- `publish_rtsp_port`
- `publish_rtsp_path`
- `channel_no`
- `display_name`
- `site_name`
- any scene-specific output behavior or business label

`device_code` should be treated as legacy and kept only for compatibility during migration. It should not be expanded further as a primary scene-model concept.

### Base-config-owned fields

These move into reusable instance objects:

#### 视频源

- input URL
- source type
- resolution metadata
- frame size
- fps
- format
- installation metadata

#### 第三方服务

- object storage endpoint / bucket / keys
- token service URL
- alarm service URL
- tenant or service-side connection metadata

## Slot-Based Template Model

The core change is to stop treating template placeholders as generic flat vars and instead treat them as **declared slots**.

### Template slot categories

Templates may declare:

- `input` slots
- `service` slots
- `output` slots

Examples:

- `video_input_main`
- `object_storage_main`
- `token_service_main`
- `alarm_service_main`
- `stream_output_main`

### Meaning of slots

A slot expresses a requirement, not an instance.

Examples:

- `video_input_main` means this template requires one concrete video input.
- `object_storage_main` means this template requires one object storage service instance.
- `stream_output_main` means this template produces a stream and needs scene-level output binding.

## Scene Binding Model

Scene config binds template slots to concrete values.

### Input binding

Example:

```json
{
  "input_bindings": {
    "video_input_main": {
      "video_source_ref": "gate_cam_01"
    }
  }
}
```

### Service binding

Example:

```json
{
  "service_bindings": {
    "object_storage_main": {
      "service_ref": "minio_prod_main"
    },
    "token_service_main": {
      "service_ref": "token_service_prod"
    },
    "alarm_service_main": {
      "service_ref": "alarm_center_prod"
    }
  }
}
```

### Output binding

Example:

```json
{
  "output_bindings": {
    "stream_output_main": {
      "publish_hls_path": "./web/hls/cam1/index.m3u8",
      "publish_rtsp_port": 8555,
      "publish_rtsp_path": "/live/cam1"
    }
  }
}
```

### Scene metadata

Scene keeps business-facing labels:

- `display_name`
- `site_name`
- `channel_no`

These are scene-level values and should not live in templates.

## Backward Compatibility Strategy

Phase 1 must preserve the existing agent runtime config format.

That means:

- `render_config.py` may continue producing the current final flat config shape.
- Agent runtime does not need to understand slots yet.
- Binding logic is introduced in the config-render pipeline, not in the agent runtime.

Compatibility rules:

1. If new slot bindings exist, they take priority.
2. If old flat fields still exist, they remain supported during migration.
3. Existing templates and scene configs must continue rendering during the transition.

## Existing Field Migration Matrix

### Input-related

- `rtsp_url`
  - Current location: scene/profile params
  - Target location: video source instance referenced from scene input binding
  - Compatibility: continue supporting direct inline `rtsp_url`

### Output-related

- `publish_hls_path`
  - Current location: scene/profile params
  - Target location: scene output binding
- `publish_rtsp_port`
  - Current location: scene/profile params
  - Target location: scene output binding
- `publish_rtsp_path`
  - Current location: scene/profile params
  - Target location: scene output binding

### Scene label fields

- `channel_no`
  - Current location: scene/profile params and used by alarm external API
  - Target location: scene metadata or output binding context
- `display_name`
  - Current location: scene/profile params
  - Target location: scene metadata
- `site_name`
  - Current location: scene/profile params
  - Target location: scene metadata
- `device_code`
  - Current location: scene/profile params
  - Target location: legacy compatibility only in phase 1

### Third-party service fields

- `minio_endpoint`
  - Current location: template params
  - Target location: object storage service instance
- `minio_bucket`
  - Current location: template params
  - Target location: object storage service instance
- `minio_access_key`
  - Current location: template params
  - Target location: object storage service instance
- `minio_secret_key`
  - Current location: template params
  - Target location: object storage service instance
- `external_get_token_url`
  - Current location: template params
  - Target location: token service instance
- `external_put_message_url`
  - Current location: template params
  - Target location: alarm service instance
- `tenant_code`
  - Current location: template params
  - Target location: token/alarm service instance, with optional scene-level override if needed later

## Cross-Repo Responsibilities

### 3588AdminBackend

Admin backend changes:

- Extend template asset model to expose slot declarations.
- Extend scene config model to store slot bindings.
- Maintain `视频源` and `第三方服务` as reusable base config objects.
- Update scene-config UI so users bind template slots to concrete instances.
- Update preview pipeline inputs to pass structured bindings to the renderer.

### OrangePi3588Media

Media service changes:

- Upgrade template JSON model to support explicit slot declarations.
- Update `render_config.py` to resolve slot bindings into the current runtime config format.
- Keep final generated runtime config compatible with the current agent in phase 1.
- Support fallback rendering for older templates and profiles during migration.

## Rendering Strategy

Rendering should become a two-stage process.

### Stage 1: Resolve scene bindings

Resolve:

- video source refs
- third-party service refs
- scene output parameters

into a structured bound scene model.

### Stage 2: Expand into final runtime config

Expand the bound scene model into the current flat runtime config fields expected by the agent.

Examples:

- resolved video source URL becomes runtime `rtsp_url`
- resolved object storage instance becomes runtime `minio_*`
- resolved alarm/token services become runtime `external_*` and `tenant_code`

This lets us modernize the model without forcing an immediate runtime-schema rewrite.

## UI Implications

### Template page

Template page should gradually shift from editing concrete values to editing:

- graph structure
- default technical parameters
- declared slots

It should no longer encourage editing concrete service endpoints or stream addresses inside templates.

### Scene page

Scene page becomes the main assembly workspace.

It should expose:

- input bindings
- service bindings
- output bindings
- scene labels and business fields

### Base-config pages

These remain the concrete instance maintenance surfaces:

- video source list/detail
- third-party service list/detail

## Phased Rollout

### Phase 1

- Keep current runtime config shape.
- Add slot-aware scene bindings.
- Add renderer logic that expands new bindings into old flat values.
- Preserve legacy flat template/profile fields.

### Phase 2

- Move standard templates to explicit slot declarations.
- Stop storing real service endpoints in new template definitions.
- Prefer video-source refs over inline stream URLs.

### Phase 3

- Remove or deprecate legacy flat substitutions from template authoring.
- Reduce compatibility code once all standard and active custom configs are migrated.

## Risks

### 1. Dual-model complexity during migration

Supporting both legacy flat fields and new bindings will increase renderer complexity temporarily.

Mitigation:

- Keep priority order explicit.
- Add fixture-based render tests for old and new models.

### 2. Template authoring confusion

Users may still expect templates to own instance values.

Mitigation:

- Shift template UI away from concrete service editing.
- Make scene config the clear assembly surface.

### 3. Cross-repo drift

If backend and media-repo schema changes are not kept aligned, preview and apply flows will break.

Mitigation:

- Treat slot/binding schema as a shared contract.
- Land cross-repo fixture tests around the render boundary.

## Testing Strategy

### Admin backend

- Unit tests for slot-aware scene models
- Unit tests for binding persistence
- UI tests for scene binding forms
- Preview tests for structured binding expansion

### Media repo

- Fixture tests for template slot declarations
- Fixture tests for legacy-template rendering
- Fixture tests for new scene-binding rendering
- Golden tests for final runtime config output

## Recommendation

Use the ideal layered model now, but keep runtime compatibility in phase 1:

- Template defines requirements and defaults.
- Base config provides reusable concrete instances.
- Scene config performs all actual binding.
- Render pipeline expands the new structure into the current agent runtime config.

This delivers the clean architecture we want without forcing a dangerous all-at-once runtime rewrite.
