# WP-07 Device Ledger and Fault Quality Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Add versioned, explainable device-ledger and fault-maintenance quality policies that produce immutable execution results, bounded violation samples, and drill-down quality scores without changing source assets. **Architecture:** Existing closed RuleSpec and `quality.check` remain the platform-level authoring and execution foundation. WP-07 adds a deterministic device-domain policy overlay for the canonical WP-04 asset catalog and WP-05 published fault/cause/action codes: one immutable policy version selects allowlisted device checks and weights, each run evaluates a bounded canonical snapshot, and append-only result tables preserve rule, asset, field, source, and mapping evidence. WP-08 will consume violations later; WP-07 does not create or mutate remediation tickets. **Tech Stack:** Flask, SQLAlchemy, PostgreSQL JSONB, Alembic, Vue 2, Vuetify, pytest. --- ## Global Constraints - Reuse `device_assets`, `device_asset_source_mappings`, `device_asset_versions`, and published `device_semantic_codes`; never rewrite or delete them during quality evaluation. - Reuse the platform's deny-by-default RBAC. Viewer may read. Editor/admin may create drafts and execute published policies. Publication requires admin permission plus the unique accountable `asset_manager` for `device_quality/DEVICE_QUALITY`. - Add `device_quality` to the governed responsibility resource types and require exactly one accountable device asset manager. - A device-quality policy is a closed allowlist, not arbitrary Python, SQL, CEL, regular-expression source, or an AI-generated executable. - The first policy contains exactly these checks: asset identity completeness, asset context completeness, normalized source-code uniqueness, component parent resolution, fault-code mapping, fault cause/action completeness, and maintenance closure. - Policy rule codes are stable. Draft revisions may change enabled state, severity, weight, and bounded allowlisted parameters only. Enabled weights must be positive and sum to 100. - Only one published version is active. Publishing a new version appends a new immutable version and supersedes the prior active version without deleting its evidence. - Every run binds the exact policy-version UID and content hash. A run captures evaluated asset/version/mapping evidence so later catalog changes cannot alter historical results. - Quality execution is bounded to 5,000 assets per run, 100 violation samples per rule, and 1,000 asset scores per response page. Counts remain exact even when samples are truncated. - Violation samples contain platform UIDs, field names, safe messages, and bounded redacted evidence only. Credentials, connection details, personal contact data, and raw operating measurements are rejected. - Overall score is the sum of each enabled rule's `weight × pass_rate`; rules with zero applicable records score their full weight and report `not_applicable`. - Per-asset score uses only rules applicable to that asset. An asset with no applicable enabled rule receives 100 and `not_applicable`. - Fault rules operate on `alarm.attributes.fault_code`, `cause_code`, and `action_code`; maintenance closure operates on `maintenance_record.attributes.device_source_code`, `fault_source_code`, `status`, `completed_at`, and `action_code`. Field names are explicit in the versioned policy. - `source_code` format consistency uses a server-owned allowlisted format identifier, not caller-supplied regular expressions. - Schema drift remains a partial platform capability; WP-07 validates the canonical device contract and code fields but does not build a general source-schema diff engine. - Do not create WP-08 remediation issues, AI root-cause conclusions, automatic repairs, predictive maintenance, or time-series storage. - Validation follows the user-approved rule: run only WP-07 domain, persistence, API, permission, frontend, migration, contract, release-copy, and local browser checks; do not run the full repository regression. - Continue on `codex/dataops-phase1-equipment-governance`; do not push or deploy remotely. ### Task 1: Closed Device-Quality Policy and Deterministic Evaluation **Files:** - Create: `app/core/data_research/device_quality.py` - Modify: `app/core/data_research/errors.py` - Create: `tests/data_research/test_device_quality.py` **Interfaces:** - Produce `DeviceQualityPolicyVersionRecord`, `DeviceQualityRunRecord`, `DeviceQualityRuleResultRecord`, `DeviceQualityViolationRecord`, and `DeviceQualityAssetScoreRecord`. - Produce `validate_device_quality_rules`, `DeviceQualityService.bootstrap`, `revise`, `publish`, `profile`, `versions`, `run`, `runs`, `get_run`, `violations`, and `asset_scores`. - Repository boundary supplies policy versions, active assets with mappings, published semantic codes, immutable run/result/sample persistence, and bounded searches. - [x] **Step 1: Write failing policy and evaluation tests** Cover the seven stable rule codes, exact enabled-weight total, unsupported keys and parameters, secret rejection, draft version immutability, accountable-manager publication, one active published version, exact score arithmetic, zero-applicable behavior, every ledger/fault/maintenance rule, source and mapping evidence, 5,000-asset boundary, 100-sample truncation, and no source mutation. - [x] **Step 2: Verify RED** Run: ```bash PYTHONPATH=. .venv/bin/pytest -q \ tests/data_research/test_device_quality.py ``` Expected: collection fails because `device_quality` does not exist. - [x] **Step 3: Implement the minimal closed policy and evaluator** Normalize only server-allowlisted rule fields and format identifiers. Evaluate immutable asset snapshots and published semantic-code sets. Persist exact counts separately from bounded samples. Reject stale profile revisions and invalid publication/run transitions with `409`. - [x] **Step 4: Verify GREEN** Run the Task 1 command and expect all tests to pass. ### Task 2: PostgreSQL Quality Policy, Run, Result, Sample, and Score Ledger **Files:** - Modify: `app/models/data_research.py` - Create: `app/core/data_research/device_quality_repository.py` - Create: `migrations/versions/20260729_320_device_quality.py` - Create: `migrations/versions/20260729_330_device_quality_responsibility_type.py` - Modify: `tests/test_database_migrations.py` - Create: `tests/integration/test_device_quality_postgres.py` **Interfaces:** - Add `device_quality_profiles`, `device_quality_profile_versions`, `device_quality_runs`, `device_quality_rule_results`, `device_quality_violation_samples`, and `device_quality_asset_scores`. - Use UUIDv7 identities, JSONB policy/evidence snapshots, profile-version and run-result uniqueness, `FOR UPDATE` publication locks, and data-preserving downgrade. - Active policy is the newest published version not superseded by another published version. - Extend the existing responsibility-scope database allowlist with `device_quality`; preserve assignments during application rollback. - [x] **Step 1: Write failing migration and real-PostgreSQL tests** Cover schema constraints, idempotent bootstrap, immutable versions, publication serialization, exact run/profile binding, exact counts with truncated samples, asset/source/mapping evidence, per-asset scores, bounded filters, and cleanup limited to test-owned rows. - [x] **Step 2: Verify RED** Run: ```bash TEST_DATABASE_URL=postgresql+psycopg2://dataops:dataops-test-password@127.0.0.1:15432/dataops \ PYTHONPATH=. .venv/bin/pytest -q \ tests/test_database_migrations.py::test_device_quality_migration_is_non_destructive_and_reversible \ tests/integration/test_device_quality_postgres.py ``` Expected: failure because migration `20260729_320` and the repository do not exist. - [x] **Step 3: Implement migration, models, and repository** Keep historical policy/run evidence on downgrade. Use database constraints for allowed statuses, severity, score ranges, nonnegative counts, one rule result per run/rule, one asset score per run/asset, and one violation sample per run/rule/asset/field identity. - [x] **Step 4: Upgrade local PostgreSQL and verify GREEN** Upgrade the isolated local database to `20260729_320`, then rerun the Task 2 command with `TEST_DATABASE_URL`. ### Task 3: Permission-Controlled Device-Quality API **Files:** - Modify: `app/api/data_development/routes.py` - Modify: `app/core/system/permissions.py` - Modify: `app/core/governance/responsibilities.py` - Create: `tests/data_research/test_device_quality_api.py` - Modify: `tests/test_permission_matrix.py` - Modify: `tests/core/governance/test_responsibilities.py` **Interfaces:** - Produce: - `GET /api/development/v1/device-quality/profile` - `POST /api/development/v1/device-quality/bootstrap` - `POST /api/development/v1/device-quality/profile/versions` - `GET /api/development/v1/device-quality/profile/versions` - `POST /api/development/v1/device-quality/profile/versions/{version_uid}/publish` - `POST /api/development/v1/device-quality/runs` - `GET /api/development/v1/device-quality/runs` - `GET /api/development/v1/device-quality/runs/{run_uid}` - `GET /api/development/v1/device-quality/runs/{run_uid}/violations` - `GET /api/development/v1/device-quality/runs/{run_uid}/asset-scores` - [x] **Step 1: Write failing API, permission, and responsibility tests** Cover viewer reads and write denial, editor bootstrap/revise/execute, editor publication denial, admin platform permission plus accountable-manager runtime denial, safe pagination/filters, closed error envelopes, and `device_quality` responsibility validation. - [x] **Step 2: Verify RED** Run: ```bash PYTHONPATH=. .venv/bin/pytest -q \ tests/data_research/test_device_quality_api.py \ tests/test_permission_matrix.py \ tests/core/governance/test_responsibilities.py ``` Expected: failure because the routes, permissions, and responsibility type do not exist. - [x] **Step 3: Implement API and authorization** Add `device-quality:edit` and `device-quality:execute` to editor/admin and `device-quality:publish` to admin. Reads remain on `governance:read`; the service repeats the unique accountable-manager check for publication. - [x] **Step 4: Verify GREEN** Run the Task 3 command and expect all tests to pass. ### Task 4: Device-Quality Workbench and Delivery Evidence **Files:** - Modify: `frontend/src/api/dataDevelopment.js` - Modify: `frontend/src/router/routes.js` - Modify: `frontend/src/views/dataGovernance/development/index.vue` - Create: `frontend/src/views/dataGovernance/development/deviceQuality.vue` - Create: `frontend/src/views/dataGovernance/development/deviceQualityModel.js` - Create: `frontend/tests/device-quality-model.test.mjs` - Modify: `docs/architecture/OPENAPI.yaml` - Modify: `docs/architecture/DATA_MODEL.md` - Modify: `docs/FUNCTION_MODULE_CENSUS_20260726.md` - Modify: `docs/DATAOPS_PHASE1_3_MONTH_WORK_PLAN_20260729.md` - Modify: `deployment/app/` for the WP-07 backend subset. **Interfaces:** - Produce `/data-governance/development/device-quality` with policy/version status, seven rule definitions, last-run score, rule pass rates, violation samples, asset-score drill-down, source evidence, permission-aware bootstrap/revise/publish/run controls, and a clear boundary that remediation belongs to WP-08. - [x] **Step 1: Write failing frontend model tests** Cover policy/rule/status labels, score and pass-rate formatting, not-applicable handling, severity labels, permission-aware mutations, and evidence summaries. - [x] **Step 2: Verify RED** Run: ```bash cd frontend node --test tests/device-quality-model.test.mjs ``` Expected: failure because the frontend model module does not exist. - [x] **Step 3: Implement the workbench** Add the development-center entry and responsive workbench. Keep historical policy/run evidence readable to viewers; hide unavailable mutations; show exact/truncated sample counts and the WP-08 boundary. - [x] **Step 4: Regenerate contracts and update ledgers** Run: ```bash .venv/bin/python scripts/generate_openapi.py \ --output docs/architecture/OPENAPI.yaml ``` Record OBS-07 and OBS-08 as engineering complete pending enterprise data acceptance. Record DQA-02 and DQA-04 as partially built because WP-07 supplies device-domain completeness/uniqueness profiles and asset/domain scores but not a general profiling platform. Keep DQA-07 partial because general schema drift remains outside WP-07. - [x] **Step 5: Run targeted verification** Run only the WP-07 domain, PostgreSQL, API, permission, responsibility, migration, OpenAPI, frontend model, targeted lint, production build, release-copy parity, and local browser workflow. In the browser bootstrap a draft, publish it as the accountable asset manager, run it against local device/alarm/maintenance data, inspect score and violation evidence, and confirm zero console errors. Run `git diff --check`. - [x] **Step 6: Commit** Create one independently reversible WP-07 engineering commit. Do not push.