diff --git a/docs/superpowers/specs/2026-04-29-template-scene-binding-design.md b/docs/superpowers/specs/2026-04-29-template-scene-binding-design.md new file mode 100644 index 0000000..13d98fd --- /dev/null +++ b/docs/superpowers/specs/2026-04-29-template-scene-binding-design.md @@ -0,0 +1,462 @@ +# 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.