mirror of
https://github.com/azaion/loader.git
synced 2026-04-22 08:36:31 +00:00
[AZ-181] Final impl report
Made-with: Cursor
This commit is contained in:
@@ -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
|
||||||
@@ -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
|
||||||
@@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
## Current Step
|
## Current Step
|
||||||
flow: existing-code
|
flow: existing-code
|
||||||
step: 9
|
step: 10
|
||||||
name: Implement
|
name: Run Tests
|
||||||
status: in_progress
|
status: not_started
|
||||||
sub_step: 6 — Launch Batch 2 implementers
|
sub_step: 0
|
||||||
retry_count: 0
|
retry_count: 0
|
||||||
current_task: Batch 2 (AZ-185, AZ-186)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user