apiVersion: jenkins.io/v1 kind: PipelineActivity metadata: annotations: lighthouse.jenkins-x.io/cloneURI: https://github.com/greencapitaltrade/bifrost.git lighthouse.jenkins-x.io/job: release creationTimestamp: "2026-07-31T04:01:45Z" generation: 7 labels: branch: main build: "168" context: release created-by-lighthouse: "true" event-GUID: 86d12f64-8c94-11f1-8147-b93589bc6482 lighthouse.jenkins-x.io/baseSHA: 62957dd66e91b8c2b2a2405dd4c2ab5d42280e8c lighthouse.jenkins-x.io/branch: main lighthouse.jenkins-x.io/buildNum: "1785470505412" lighthouse.jenkins-x.io/context: release lighthouse.jenkins-x.io/id: apitaltrade-bifrost-main-release-js8hw lighthouse.jenkins-x.io/job: release lighthouse.jenkins-x.io/lastCommitSHA: 62957dd66e91b8c2b2a2405dd4c2ab5d42280e8c lighthouse.jenkins-x.io/refs.org: greencapitaltrade lighthouse.jenkins-x.io/refs.repo: bifrost lighthouse.jenkins-x.io/type: postsubmit owner: greencapitaltrade podName: apitaltrade-bifrost-main-release-h5dms-from-build-pack-pod provider: github repository: bifrost tekton.dev/pipeline: apitaltrade-bifrost-main-release managedFields: - apiVersion: jenkins.io/v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:labels: f:branch: {} f:context: {} f:owner: {} f:provider: {} f:repository: {} f:spec: f:lastCommitMessage: {} f:lastCommitSHA: {} f:releaseNotesURL: {} f:version: {} manager: jx-changelog-0.10.29 operation: Update time: "2026-07-31T04:06:27Z" - apiVersion: jenkins.io/v1 fieldsType: FieldsV1 fieldsV1: f:spec: f:completedTimestamp: {} manager: jx-promote-0.6.45 operation: Update time: "2026-07-31T04:07:57Z" - apiVersion: jenkins.io/v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:annotations: .: {} f:lighthouse.jenkins-x.io/cloneURI: {} f:lighthouse.jenkins-x.io/job: {} f:labels: .: {} f:build: {} f:created-by-lighthouse: {} f:event-GUID: {} f:lighthouse.jenkins-x.io/baseSHA: {} f:lighthouse.jenkins-x.io/branch: {} f:lighthouse.jenkins-x.io/buildNum: {} f:lighthouse.jenkins-x.io/context: {} f:lighthouse.jenkins-x.io/id: {} f:lighthouse.jenkins-x.io/job: {} f:lighthouse.jenkins-x.io/lastCommitSHA: {} f:lighthouse.jenkins-x.io/refs.org: {} f:lighthouse.jenkins-x.io/refs.repo: {} f:lighthouse.jenkins-x.io/type: {} f:podName: {} f:tekton.dev/pipeline: {} f:spec: .: {} f:baseSHA: {} f:batchPipelineActivity: {} f:build: {} f:context: {} f:gitBranch: {} f:gitOwner: {} f:gitRepository: {} f:gitUrl: {} f:message: {} f:pipeline: {} f:startedTimestamp: {} f:status: {} f:steps: {} manager: jx-build-controller operation: Update time: "2026-07-31T04:10:27Z" name: greencapitaltrade-bifrost-main-168 namespace: jx resourceVersion: "230756346" uid: 611f1ca1-6c9c-41e4-86d3-a9f7e2b430b5 spec: baseSHA: 62957dd66e91b8c2b2a2405dd4c2ab5d42280e8c batchPipelineActivity: {} build: "168" completedTimestamp: "2026-07-31T04:07:27Z" context: release gitBranch: main gitOwner: greencapitaltrade gitRepository: bifrost gitUrl: https://github.com/greencapitaltrade/bifrost.git lastCommitMessage: | feat(asset): expose live device state (ignition, immobiliser) per IoT device The API returned device identity and telemetry but nothing about the state a device reads or drives, so VoltCred could send engine_cutoff and never learn whether the vehicle was actually immobilised. Adds `asset.iot.device.device_state`: a deep-merged JSON blob, one envelope per key -- {"ignition": {"v": true, "at": "...", "src": "telemetry"}}. Telemetry frames are routinely partial (a location-only frame carries no power block), so each frame merges onto the previous state rather than replacing it: dicts recurse, arrays replace wholesale, an absent key is "no update" while an explicit null overwrites, and a per-key timestamp guard stops a replayed or reordered frame regressing a newer value. Merges run under SELECT ... FOR UPDATE so a consumer frame and a heartbeat cannot lose each other's write. `src` separates what the device reported (telemetry) from what we merely commanded (command) and it has not confirmed. Terra and Clean Electric report real immobiliser state and were already sending it -- Bifrost dropped it on the floor. GT06 reports none, so its cutoff surfaces as observed=false rather than as a claim the vehicle is immobilised. State definitions come from the feature registry, not from code: asset.iot.feature declares each capability's fields, post_init_hook materialises them into asset.iot.feature.data (67 rows), and a device's keys derive from its IoT type. Adding a sensor is a registry row -- no column, no migration, no GraphQL change (test_adding_a_sensor_needs_no_code_change). Protocol extras (GT06 dyd/alm*/sta1) are stored raw and uninterpreted. dyd is Concox's fuel/power cutoff status, but its bit layout is not spec-confirmed -- Traccar keeps the raw byte and PR #121 removed an invented bit1 -> immobilized mapping. A test asserts a dyd byte never populates `immobilized`. Fixes found along the way: - _store_complete_packet never recorded ignition, so GT06 and Clean Electric had no ignition state at all - feature_codes was never written by anything, so has_gps / has_control / is_report_eligible computed off an empty list for every device - derive_iot_status read getattr(self, 'engine_status') on asset.asset, a field that does not exist -- the 'idle' branch was unreachable and an ACC-capable vehicle idling at a light reported 'stopped' 35 tests. Full suite unchanged at 19 failed / 143 errors (pre-existing, see docs/asset-management-test-recovery.md) with 464 -> 499 tests. Co-Authored-By: Claude Opus 5 (1M context) lastCommitSHA: 7f6cc68fb646fd5407c40b8d85ad5d35df347cce message: 'Tasks Completed: 1 (Failed: 0, Cancelled 0), Skipped: 0' pipeline: greencapitaltrade/bifrost/main releaseNotesURL: https://github.com/greencapitaltrade/bifrost/releases/tag/v6.88.0 startedTimestamp: "2026-07-31T04:01:45Z" status: Running steps: - kind: Stage stage: completedTimestamp: "2026-07-31T04:07:27Z" name: Release startedTimestamp: "2026-07-31T04:06:27Z" status: Succeeded - kind: Promote promote: environment: staging pullRequest: pullRequestURL: https://github.com/greencapitaltrade/mcu/pull/5044 startedTimestamp: "2026-07-31T04:07:27Z" status: Succeeded startedTimestamp: "2026-07-31T04:07:27Z" status: Succeeded - kind: Stage stage: completedTimestamp: "2026-07-31T04:10:25Z" name: from build pack startedTimestamp: "2026-07-31T04:01:52Z" status: Succeeded steps: - completedTimestamp: "2026-07-31T04:02:19Z" name: Git Clone startedTimestamp: "2026-07-31T04:01:52Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:25Z" name: Next Version startedTimestamp: "2026-07-31T04:02:20Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:31Z" name: Jx Variables startedTimestamp: "2026-07-31T04:02:25Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:31Z" name: Setup Npm Nexus startedTimestamp: "2026-07-31T04:02:31Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:34Z" name: Setup Pip Cache startedTimestamp: "2026-07-31T04:02:31Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:35Z" name: Process Config Templates startedTimestamp: "2026-07-31T04:02:34Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:35Z" name: Update Asset Management Version startedTimestamp: "2026-07-31T04:02:35Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:40Z" name: Check Registry startedTimestamp: "2026-07-31T04:02:36Z" status: Succeeded - completedTimestamp: "2026-07-31T04:06:17Z" name: Build Container Build startedTimestamp: "2026-07-31T04:02:40Z" status: Succeeded - completedTimestamp: "2026-07-31T04:06:27Z" name: Promote Changelog startedTimestamp: "2026-07-31T04:06:17Z" status: Succeeded - completedTimestamp: "2026-07-31T04:06:31Z" name: Promote Helm Release startedTimestamp: "2026-07-31T04:06:27Z" status: Succeeded - completedTimestamp: "2026-07-31T04:08:00Z" name: Promote Jx Promote startedTimestamp: "2026-07-31T04:06:31Z" status: Succeeded - completedTimestamp: "2026-07-31T04:10:25Z" name: Publish Org Kb startedTimestamp: "2026-07-31T04:08:00Z" status: Succeeded - kind: Stage stage: name: from build pack startedTimestamp: "2026-07-31T04:01:52Z" status: Running steps: - completedTimestamp: "2026-07-31T04:02:19Z" name: Git Clone startedTimestamp: "2026-07-31T04:01:52Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:25Z" name: Next Version startedTimestamp: "2026-07-31T04:02:20Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:31Z" name: Jx Variables startedTimestamp: "2026-07-31T04:02:25Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:31Z" name: Setup Npm Nexus startedTimestamp: "2026-07-31T04:02:31Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:34Z" name: Setup Pip Cache startedTimestamp: "2026-07-31T04:02:31Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:35Z" name: Process Config Templates startedTimestamp: "2026-07-31T04:02:34Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:35Z" name: Update Asset Management Version startedTimestamp: "2026-07-31T04:02:35Z" status: Succeeded - completedTimestamp: "2026-07-31T04:02:40Z" name: Check Registry startedTimestamp: "2026-07-31T04:02:36Z" status: Succeeded - completedTimestamp: "2026-07-31T04:06:17Z" name: Build Container Build startedTimestamp: "2026-07-31T04:02:40Z" status: Succeeded - completedTimestamp: "2026-07-31T04:06:27Z" name: Promote Changelog startedTimestamp: "2026-07-31T04:06:17Z" status: Succeeded - completedTimestamp: "2026-07-31T04:06:31Z" name: Promote Helm Release startedTimestamp: "2026-07-31T04:06:27Z" status: Succeeded - name: Promote Jx Promote startedTimestamp: "2026-07-31T04:02:00Z" status: Running - name: Publish Org Kb status: Pending version: 6.88.0 status: {}