From 7d690e1fb4c92f83329993a5a3bd7b236c0d57fc Mon Sep 17 00:00:00 2001 From: Oleksandr Bezdieniezhnykh Date: Wed, 15 Apr 2026 07:33:13 +0300 Subject: [PATCH] [AZ-181] Final impl report Made-with: Cursor --- .../todo/AZ-183_resources_table_update_api.md | 66 +++++++++++++++++++ ...mentation_report_security_modernization.md | 44 +++++++++++++ _docs/_autopilot_state.md | 9 ++- 3 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 _docs/02_tasks/todo/AZ-183_resources_table_update_api.md create mode 100644 _docs/03_implementation/implementation_report_security_modernization.md diff --git a/_docs/02_tasks/todo/AZ-183_resources_table_update_api.md b/_docs/02_tasks/todo/AZ-183_resources_table_update_api.md new file mode 100644 index 0000000..31045ec --- /dev/null +++ b/_docs/02_tasks/todo/AZ-183_resources_table_update_api.md @@ -0,0 +1,66 @@ +# Resources Table & Update Check API + +**Task**: AZ-183_resources_table_update_api +**Name**: Resources Table & Update Check API +**Description**: Add Resources table to admin API PostgreSQL DB and implement POST /get-update endpoint for fleet OTA updates +**Complexity**: 3 points +**Dependencies**: None +**Component**: Admin API +**Tracker**: AZ-183 +**Epic**: AZ-181 + +## Problem + +The fleet update system needs a server-side component that tracks published artifact versions and tells devices what needs updating. CI/CD publishes encrypted artifacts to CDN; the server must store metadata (version, URL, hash, encryption key) and serve it to devices on request. + +## Outcome + +- Resources table stores per-artifact metadata populated by CI/CD +- Devices call POST /get-update with their current versions and get back only what's newer +- Server-side memory cache handles 2000+ devices polling every 5 minutes without DB pressure + +## Scope + +### Included +- Resources table migration (resource_name, dev_stage, architecture, version, cdn_url, sha256, encryption_key, size_bytes, created_at) +- POST /get-update endpoint: accepts device's current versions + architecture + dev_stage, returns only newer resources +- Server-side memory cache invalidated on CI/CD publish +- Internal endpoint or direct DB write for CI/CD to publish new resource versions + +### Excluded +- CI/CD pipeline changes (AZ-186) +- Loader-side update logic (AZ-185) +- Device provisioning (AZ-187) + +## Acceptance Criteria + +**AC-1: Resources table created** +Given the admin API database +When the migration runs +Then the Resources table exists with all required columns + +**AC-2: Update check returns newer resources** +Given Resources table has annotations version 2026-04-13 +When device sends POST /get-update with annotations version 2026-02-25 +Then response includes annotations with version, cdn_url, sha256, encryption_key, size_bytes + +**AC-3: Current device gets empty response** +Given device already has the latest version of all resources +When POST /get-update is called +Then response is an empty array + +**AC-4: Memory cache avoids repeated DB queries** +Given 2000 devices polling every 5 minutes +When POST /get-update is called repeatedly +Then the latest versions are served from memory cache, not from DB on every request + +**AC-5: Cache invalidated on publish** +Given a new resource version is published via CI/CD +When the publish endpoint/function completes +Then the next POST /get-update call returns the new version + +## Constraints + +- Must integrate with existing admin API (linq2db + PostgreSQL) +- encryption_key column must be stored securely (encrypted at rest in DB or via application-level encryption) +- Response must include encryption_key only over HTTPS with valid JWT diff --git a/_docs/03_implementation/implementation_report_security_modernization.md b/_docs/03_implementation/implementation_report_security_modernization.md new file mode 100644 index 0000000..b91586b --- /dev/null +++ b/_docs/03_implementation/implementation_report_security_modernization.md @@ -0,0 +1,44 @@ +# Implementation Report: Loader Security Modernization (AZ-181) + +**Epic**: AZ-181 +**Date**: 2026-04-15 +**Total Tasks**: 5 implemented (1 out-of-repo) +**Total Complexity**: 18 points implemented + +## Summary + +Implemented the loader's security modernization features across 2 batches: + +### Batch 1 (10 points) +- **AZ-182** TPM Security Provider — SecurityProvider ABC with TPM/legacy detection, FAPI seal/unseal, graceful fallback +- **AZ-184** Resumable Download Manager — HTTP Range resume, SHA-256 verify, AES-256 decrypt, exponential backoff +- **AZ-187** Device Provisioning Script — provision_device.sh + runbook + +### Batch 2 (8 points) +- **AZ-185** Update Manager — background update loop, version collector, model + Docker image apply, self-update last +- **AZ-186** CI/CD Artifact Publish — shared publish script, Woodpecker pipeline, encryption-compatible with download manager + +### Out of Scope +- **AZ-183** Resources Table & Update API — requires implementation in the admin API repository (`admin/`). A mock endpoint was added to `e2e/mocks/mock_api/app.py` for loader testing. + +## Test Coverage + +| Task | Unit Tests | AC Coverage | +|------|-----------|-------------| +| AZ-182 | 8 tests (1 skip without swtpm) | 6/6 | +| AZ-184 | 8 tests | 5/5 | +| AZ-185 | 10 tests | 6/6 | +| AZ-186 | 8 tests | 5/5 | +| AZ-187 | 5 tests | 5/5 | + +## Commits + +| Hash | Message | +|------|---------| +| d244799 | [AZ-182][AZ-184][AZ-187] Batch 1 | +| 9a0248a | [AZ-185][AZ-186] Batch 2 | + +## Code Review Verdicts + +- Batch 1: PASS_WITH_WARNINGS +- Batch 2: PASS_WITH_WARNINGS diff --git a/_docs/_autopilot_state.md b/_docs/_autopilot_state.md index 4355925..430043d 100644 --- a/_docs/_autopilot_state.md +++ b/_docs/_autopilot_state.md @@ -2,9 +2,8 @@ ## Current Step flow: existing-code -step: 9 -name: Implement -status: in_progress -sub_step: 6 — Launch Batch 2 implementers +step: 10 +name: Run Tests +status: not_started +sub_step: 0 retry_count: 0 -current_task: Batch 2 (AZ-185, AZ-186)