Agent
...
Updater Primary Spec
Development Tasks
21 min
schema note this task list assumes the existence of server side database tables to manage update package metadata (e g , component name, version, channel, os, arch, download url, hash, signature) based on the provided schema, a new table like updatepackages would likely be required on the server the client updater interacts primarily with the devices table (reading/updating agent versions and status) and potentially logs to agentupdatestatuslog testing note each programming task (c , s ) is followed by a corresponding unit test task (c test, s test) infrastructure/process tasks (b ) and decision tasks are tested through integration/e2e tests (phase 9) this list breaks down the prd into actionable tasks with enhanced detail, ordered logically tasks marked with \[decision needed] require human input/definition phase 1 foundation & core setup client (commandit updater go) task c1 1 initialize go project goal set up the go module for the client updater details use go (specify version, e g , 1 21+) initialize a go module named commandit com/updater/client (or similar) create a basic main go file set up standard directories (cmd/commandit updater, internal, pkg) task c1 2 implement basic configuration loading goal load core settings from a configuration file details implement loading from updater conf (use json format) define expected paths (e g , /etc/commandit/updater conf on linux/mac, %programdata%\commandit\updater conf on windows) define a go struct for configuration (initially just updateserverurl string, authsecret string, releasechannel string, publickeypathorvalue string, componentmanifestpath string, logfilepath string, logmaxsizemb int, logmaxfiles int) use libraries like viper or standard encoding/json + os handle file not found errors gracefully (log warning, use defaults) load initial required fields (ref fr cfg 001) task c1 2 test unit test configuration loading goal verify configuration loading logic details write unit tests using the testing package test cases valid json file loads correctly, file not found returns default values/no error, invalid json returns an error, correct paths are checked based on os (use build tags or runtime checks if needed) mock file system interactions task c1 3 implement basic structured logging goal set up logging to file and standard output details use the standard log/slog library configure json output format include default fields timestamp (iso8601), level (info, warn, error, debug), message log to both stdout and the file path specified in config (logfilepath, default updater log) implement basic log levels (ref fr log 001) task c1 3 test unit test logging setup goal verify logger initialization and output details write unit tests test logger initialization with different config settings (valid/invalid paths) test that logs are written to the correct destination(s) (mock file system/capture stdout) verify log message format (json) and inclusion of standard fields test log level filtering task c1 4 implement basic http client request goal make a basic check in request to the server details use the standard go net/http client create a function checkforupdates(cfg config, currentversions map\[string]string) (manifestresponse, error) implement logic to perform an http post request to cfg updateserverurl + "/v1/check" (body built in task c2 2) set appropriate timeouts (e g , 30 seconds) add required headers (content type, auth task c2 4) log the request being made and the response status code handle basic errors (connection refused, timeout, non 2xx status) and log them (ref fr upd 002) task c1 4 test unit test http client request goal verify the basic check in request logic details write unit tests using net/http/httptest mock the server endpoint (/v1/check) test cases successful request returns expected response struct, server error (5xx) returns error, client error (timeout) returns error, non 200 status code returns error, correct headers (auth, content type) are sent verify request body structure (using dummy data for now) task c1 5 implement basic cli argument parsing goal handle basic command line flags details use the standard go flag package implement flags version (prints hardcoded version string and exits), help (prints usage info and exits), checknow (task c8 1), reinstall \<component> (task c8 3) task c1 5 test unit test cli argument parsing goal verify command line flags are parsed correctly details write unit tests simulate command line arguments (e g , os args = \[]string{"cmd", " version"}) test that flags are parsed correctly and trigger expected behavior (e g , setting variables, printing output, exiting) test invalid flag combinations or values server (go hosted on do) task s1 1 initialize go project (server) goal set up the go module for the update server api details use go (specify version, e g , 1 21+) initialize a go module named commandit com/updater/server (or similar) create a basic main go task s1 2 implement basic http server goal create a running http server details use the standard go net/http package or a lightweight framework like gin or echo set up basic routing listen on a configurable port (e g , 8080) task s1 2 test unit test http server setup goal verify basic server initialization details write unit tests test server creation logic test that it listens on the configured port (can use net listen temporarily) test basic routing setup (does it register handlers?) task s1 3 create placeholder /v1/check endpoint goal implement the initial check endpoint details create an http handler function for the route post /v1/check the handler should initially return a static json response {"updates" \[]} with http status 200 and content type application/json (ref fr srv 008) task s1 3 test unit test placeholder endpoint goal verify the placeholder endpoint returns the correct static response details write unit tests using net/http/httptest create a request to the placeholder endpoint verify the response status code is 200, content type is application/json, and the body matches the expected static json {"updates" \[]} task s1 4 setup basic do deployment goal define how the server will be deployed details create a dockerfile to build the go server binary within a minimal container image (e g , alpine or distroless) define a basic digital ocean app platform spec file (spec yaml) or document steps for deploying the container to a droplet (ref tr infra 001) build & infrastructure task b1 1 setup cross compilation build pipeline goal automate building the client for all targets details configure goreleaser ( goreleaser yml) define build targets for os (windows, linux, darwin) and arch (amd64, arm64) configure output format (compressed archives or raw binaries) integrate into ci/cd if possible (ref tr build 001) task b1 2 provision basic do infrastructure goal set up necessary cloud resources details create a do app platform app (or droplet) create a do spaces bucket (specify name, region) configure dns for updates commandit com to point to the app platform app/load balancer/droplet ip (ref tr infra 001) phase 2 update check & manifest handling client task c2 1 implement system info & version gathering goal collect data needed for the check request details use runtime goos and runtime goarch for os/arch implement logic to read component versions from the local manifest json file (task c4 4 dependency, path from componentmanifestpath in config) if manifest doesn't exist or is empty, use placeholder values (e g , version "0 0 0") include versions for 'service', 'ui', 'probe', 'updater' (ref fr upd 003) task c2 1 test unit test info gathering goal verify collection of os, arch, and component versions details write unit tests mock the manifest json file content (valid, empty, missing) verify the function returns the correct os/arch for the test environment verify it correctly parses versions from the mocked manifest or returns defaults task c2 2 format /v1/check request body goal create the json payload for the check request details define go structs matching the request json structure specified in fr upd 003 (updater version, os, arch, release channel, components array) populate these structs using data from task c2 1, task c1 2 (releasechannel), and the updater's own version marshal the struct to json for the http request body (task c1 4) task c2 2 test unit test request body formatting goal verify correct json payload generation details write unit tests provide sample input data (versions, os, arch, channel) call the formatting function unmarshal the resulting json and verify all fields match the expected values and structure defined in fr upd 003 task c2 3 implement manifest response parsing goal process the update information from the server details define go structs matching the expected json response structure from fr srv 001 (updates array with name, version, url, hash sha256, signature, etc ) parse the http response body (from task c1 4) into these structs handle json parsing errors handle the case where the updates array is empty (log "no updates available") task c2 3 test unit test manifest response parsing goal verify correct parsing of server response details write unit tests provide sample valid json response strings (with updates, without updates) test parsing into the defined go structs verify all fields are populated correctly test with invalid/malformed json to ensure errors are handled task c2 4 implement auth header addition goal add the authentication secret to requests details read the authsecret field from the configuration struct (task c1 2) add an http header x commandit updater secret \<secret value> to the http request object created in task c1 4 before sending (ref nfr srv 010, fr upd 002) task c2 4 test unit test auth header goal verify the auth header is added correctly details write unit tests modify task c1 4 test to specifically check the x commandit updater secret header in the outgoing request, verifying it matches the secret provided in the test configuration task c2 5 implement release channel handling (client) goal include the client's channel in the request details ensure releasechannel is loaded from config (task c1 2) and included in the request json payload (task c2 2) (ref fr upd 003) task c2 5 test unit test release channel inclusion goal verify the release channel is included in the request body details write unit tests modify task c2 2 test to verify the release channel field in the marshaled json matches the value provided in the test configuration server task s2 1 implement auth header validation goal verify client requests using the shared secret details read the expected shared secret on the server (e g , from environment variable or secure config store) in a middleware or directly in the /v1/check handler, read the x commandit updater secret header from the incoming request compare the received secret with the expected secret using a constant time comparison function if missing or invalid, return http status 401 unauthorized or 403 forbidden (ref nfr srv 010) task s2 1 test unit test auth header validation goal verify server correctly validates the shared secret details write unit tests using net/http/httptest test cases request with valid secret returns 200 (or expected success code), request with invalid secret returns 401/403, request missing the header returns 401/403 task s2 2 implement request body parsing goal decode the client's check request details in the /v1/check handler, read and parse the json request body into the go structs defined for the request payload (matching task c2 2) handle json parsing errors by returning http status 400 bad request task s2 2 test unit test request body parsing (server) goal verify server correctly parses the client request payload details write unit tests using net/http/httptest send requests with valid json bodies matching the expected structure verify the handler correctly parses the data into go structs send requests with invalid/malformed json and verify a 400 bad request status is returned task s2 3 implement basic manifest generation goal create a dynamic manifest based on the request details implement logic that takes the parsed request data (os, arch, channel, component versions) as input query the (assumed) updatepackages table filtering by os, arch, channel for each matching package, compare its version with the client's reported version for that component name if the server version is newer, add its details (name, version, url, hash, signature) to the response updates array construct the json response according to fr srv 001 structure (ref fr srv 001) task s2 3 test unit test manifest generation goal verify correct manifest generation based on client request and package data details write unit tests mock the database query for updatepackages provide sample client request data (os, arch, channel, versions) provide sample package data in the mock db test cases client needs update, client needs multiple updates, client needs no updates, client requests invalid channel/os/arch verify the generated json response matches the expected updates based on the mocked data and version comparison logic task s2 4 implement basic server request logging goal log incoming requests details implement logging middleware or add logging within handlers log request details timestamp, source ip, method, path, status code returned, request duration use structured json format (ref nfr aud 001 partial) task s2 4 test unit test server request logging goal verify logging middleware/handler logs correctly details write unit tests using net/http/httptest capture log output (e g , using a custom slog handler) send test requests verify that log entries are generated with the expected fields (ip, method, path, status, duration) and format phase 3 package handling & verification infrastructure & process task b3 1 \[decision needed] define package structure goal document the standard layout for update packages details decide and document archive format (zip recommended for windows compatibility, tar gz for linux/mac) does it include a metadata file (e g , package json) specifying version, target component, config preservation rules, pre/post scripts? define the format of this metadata file task b3 2 setup package hosting (do spaces) goal configure the object storage for packages details configure the do spaces bucket created in task b1 2 set appropriate permissions (e g , public read via cdn, or private requiring signed urls generated by the server) enable https access task b3 3 establish signing key process goal create and secure the code signing keys details generate signing key pair (rsa 2048+ or ecdsa p 256+) securely store the private key (hsm, secure vault, encrypted file with strong access control) document the key management and rotation policy (ref nfr sec 004) task b3 4 develop/integrate signing tooling goal create a way to sign packages details choose a method use openssl command line tool, or implement signing using go crypto libraries the tool should take a package file as input, calculate its hash (sha 256), sign the hash with the private key (task b3 3), and output the signature (e g , base64 encoded) (ref fr srv 004) task b3 5 integrate signing into build pipeline goal sign packages automatically after building details add a step to the goreleaser config (task b1 1) or build script that calls the signing tool (task b3 4) for each generated package archive store the signature alongside the package or embed it in metadata (ref fr srv 005) task b3 6 develop package upload/metadata update tooling goal publish signed packages and update server info details create a script or tool (go preferred) that uploads the signed package archive (from task b3 5) to do spaces (task b3 2) updates the server side updatepackages table (assumed) with the package details component name, version, channel, os, arch, download url (spaces url), sha 256 hash, signature (ref fr srv 005) client task c3 1 implement secure package download goal download update packages reliably details enhance task c1 4's http client logic implement function downloadpackage(url, tempdestpath string) error download from the given url saving to tempdestpath use io copy with progress tracking (optional) implement retries with exponential backoff for transient network errors (e g , 5xx status codes, timeouts) ensure https is used handle download errors (log, return error) save to a secure temporary directory (os mkdirtemp) with restricted permissions (task c8 10) (ref fr upd 005, nfr sec 007) task c3 1 test unit test package download goal verify package download logic, including retries details write unit tests using net/http/httptest mock the download endpoint test cases successful download saves file correctly, server error triggers retries and eventually returns error, connection error returns error, invalid url returns error verify temporary file creation/permissions (mock os) task c3 2 implement hash verification goal verify integrity of downloaded package details implement function verifyhash(filepath, expectedhash string) error open the downloaded file at filepath calculate its sha 256 hash using crypto/sha256 compare the calculated hex encoded hash with expectedhash (from manifest) log success or failure return error on mismatch trigger rollback on error (ref fr upd 006, fr rbk 001 trigger) task c3 2 test unit test hash verification goal verify sha 256 hash calculation and comparison details write unit tests create temporary test files with known content and pre calculated sha 256 hashes test cases correct hash matches, incorrect hash returns error, error reading file returns error task c3 3 \[decision needed] define initial public key provisioning goal decide how the client gets the first verification key details choose method embed the pem encoded public key as a string constant in the go binary or have the deployment method (gpo, script) place the key file in a known location read by the updater document the chosen method task c3 4 implement public key loading goal load the verification key into memory details implement function loadpublickey(cfg config) ( crypto publickey, error) based on task c3 3 decision load from embedded string or load from file path specified in config (publickeypathorvalue) use encoding/pem and crypto/x509 (parsepkixpublickey or parsepkcs1publickey) handle errors during loading/parsing (ref fr cfg 001) task c3 4 test unit test public key loading goal verify loading of pem encoded public keys details write unit tests test loading a valid embedded pem string test loading from a valid pem file (mock file system) test loading invalid pem data (string/file) returns error test loading from non existent file path returns error task c3 5 implement signature verification goal verify authenticity of the downloaded package details implement function verifysignature(filepath, signaturebase64 string, pubkey crypto publickey) error calculate the sha 256 hash of the file at filepath decode the base64 signaturebase64 (from manifest) use appropriate crypto functions (e g , rsa verifypkcs1v15, ecdsa verifyasn1) with the hash, decoded signature, and loaded pubkey log success or failure return error on invalid signature trigger rollback on error (ref fr upd 006, fr rbk 001 trigger) task c3 5 test unit test signature verification goal verify package signature validation logic details write unit tests generate a test key pair create a test file, calculate its hash, sign the hash with the private key, base64 encode the signature test cases valid signature + correct public key verifies successfully invalid signature + correct public key returns error valid signature + incorrect public key returns error malformed signature string returns error error reading file returns error server task s3 1 update manifest generation with real data goal serve actual package details in the manifest details modify task s2 3 query the updatepackages table (assumed) based on client request parameters (os, arch, channel, components) retrieve the correct download url, sha 256 hash, and signature for available updates and populate the json response task s3 1 test unit test manifest generation (real data) goal verify manifest generation uses real package data correctly details write unit tests mock database queries to updatepackages test that the correct url, hash, and signature are retrieved from the mock db based on request parameters and included in the response test version comparison logic accurately task s3 2 ensure secure package hosting access goal confirm packages are served over https details verify do spaces/cdn configuration ensures packages are only downloadable via https urls if using signed urls, ensure the server generates them correctly (ref fr srv 002) phase 4 installation & basic update execution client task c4 1 implement disk space check goal prevent updates if insufficient space exists details implement function checkdiskspace(path string, requiredbytes int64) error use os specific apis or libraries (e g , golang org/x/sys/unix for statfs t, windows apis via syscall) to get available disk space for the volume containing path (target install dir, temp dir, backup dir) compare available space with requiredbytes (estimated download size + extracted size + backup size) return error if insufficient trigger rollback on error (ref fr upd 008, fr rbk 001 trigger) task c4 1 test unit test disk space check goal verify disk space checking logic details write unit tests mock the os specific disk space functions test cases sufficient space returns nil error, insufficient space returns error, error getting disk space returns error task c4 2 implement package extraction goal unpack the downloaded archive details implement function extractpackage(archivepath, destpath string) error use archive/zip or compress/gzip + archive/tar based on package format (task b3 1) extract contents from archivepath to destpath (a secure temporary directory task c8 10) handle extraction errors (corrupt archive etc ) (ref fr cmp 003) task c4 2 test unit test package extraction goal verify archive extraction logic details write unit tests create sample zip and tar gz archives test extraction to a temporary directory (mock os) verify expected files/directories exist after extraction test with corrupt archives to ensure errors are returned task c4 3 implement basic file replacement goal copy extracted files to the target component directory details implement function replacecomponentfiles(extractedpath, targetpath string, preserverules \[]string) error recursively copy files/dirs from extractedpath to targetpath before copying, check preserverules (from package metadata task b3 1) and skip overwriting specified files/dirs in targetpath ensure correct file permissions are set on new/replaced files handle file operation errors (permissions, disk full) trigger rollback on critical errors (ref fr cmp 003, fr rbk 001 trigger) task c4 3 test unit test file replacement goal verify file copying and preservation logic details write unit tests mock file system operations (os) create mock source (extracted) and target directories/files test cases simple copy replaces target files files specified in preserverules are not overwritten test handling of permission errors during copy test handling of disk full errors during copy task c4 4 implement local component manifest r/w goal track installed components locally details define the manifest json structure (e g , {"components" \[{"name" " ", "version" " ", "path" " "}]}) implement readmanifest(path string) (manifest, error) and writemanifest(path string, manifest manifest) error writemanifest must be atomic (write to temp file, os rename) ensure file permissions are restricted (task c8 9) use path from componentmanifestpath config (ref fr cfg 003) task c4 4 test unit test manifest r/w goal verify reading, writing, and atomicity of the local manifest details write unit tests mock file system test readmanifest with valid json, invalid json, missing file test writemanifest verify it writes to temp file first, then renames verify the written json content matches the input struct verify file permissions are set (mock os chmod) task c4 5 implement basic service/process stop goal stop the target component before update details implement function stopcomponent(componentname string) error use os specific commands/apis taskkill /f /im \<process name> or stop service \<service name> (win); pkill \<process name> or launchctl unload \<plist path> (mac); pkill \<process name> or systemctl stop \<service name> (linux) this is the basic, non graceful version for now return error on failure (ref fr cmp 001 partial) task c4 5 test unit test basic stop component goal verify the function attempts to stop the component details write unit tests mock os/exec or relevant os apis verify the correct command/api call is made based on component name and os test handling of errors returned by the mocked command/api task c4 6 implement basic service/process start goal start the component after update details implement function startcomponent(componentname string) error use os specific commands/apis start service \<service name> (win); launchctl load \<plist path> (mac); systemctl start \<service name> (linux) return error on failure (ref fr cmp 004 partial) task c4 6 test unit test basic start component goal verify the function attempts to start the component details write unit tests mock os/exec or relevant os apis verify the correct command/api call is made based on component name and os test handling of errors returned by the mocked command/api task c4 7 implement core bootstrap logic goal handle initial agent installation details in main go, add logic check if manifest json (task c4 4) exists if not call task c2 1 c2 3 (requesting manifest for all baseline components) for each component in response call task c3 1 (download), c3 2 (hash), c3 5 (sig), c4 2 (extract), c4 3 (replace) create initial updater conf (task c1 2) with defaults/args create initial manifest json (task c4 4) with installed components call task c4 8 (install self as service) (ref fr bst 002) task c4 7 test unit test bootstrap logic goal verify the sequence of operations during initial install details write unit tests mock dependent functions (checkforupdates, downloadpackage, verifyhash, verifysignature, extractpackage, replacecomponentfiles, readmanifest, writemanifest, installservice) test cases manifest exists (bootstrap does nothing), manifest missing (verify all dependent functions are called in the correct order for each component returned by mock checkforupdates) task c4 8 implement updater service installation goal make the updater run persistently details use a library like kardianos/service or implement os specific logic sc create (win), create launchd plist and load (mac), create systemd unit file and enable (linux) ensure the service definition points to the correct updater binary path and runs as system/root (ref fr bst 002) task c4 8 test unit test service installation goal verify service installation commands/api calls details write unit tests using build tags for os specific logic mock os/exec or relevant os apis/libraries (kardianos/service) verify the correct commands (sc create, launchctl, systemctl) or library methods are called with the correct parameters (service name, binary path, user context) test error handling task c4 9 implement temporary file cleanup goal remove intermediate files details after an update attempt (success or failure/rollback), ensure temporary download directories (from task c3 1) and extraction directories (from task c4 2) are deleted using os removeall (ref fr upd 008) task c4 9 test unit test temp file cleanup goal verify temporary directories are removed details write unit tests mock os removeall create dummy temp paths call the cleanup function verify os removeall was called for the expected paths phase 5 release channels & server logic refinement server task s5 1 implement channel filtering in manifest gen goal serve only channel appropriate updates details modify task s3 1 when querying the updatepackages table, filter available packages not only by os/arch but also strictly by the release channel provided in the client request only include packages matching the requested channel in the response manifest task s5 1 test unit test channel filtering goal verify manifest generation respects the release channel filter details write unit tests modify task s3 1 test mock database queries provide sample client requests with different channels ('stable', 'beta') provide mock package data with different versions assigned to different channels verify the response only includes packages matching the requested channel task s5 2 implement channel management tooling/api goal allow promotion of builds between channels details create a secured api endpoint (e g , post /v1/admin/promote) or a cli tool input component name, version, target channel (e g , 'stable') logic update the updatepackages table (or related metadata) to assign the specified version to the target channel for relevant os/arch combinations requires authentication/authorization (ref fr srv 003) task s5 2 test unit test channel management api/tool goal verify channel promotion logic details write unit tests mock database update calls test the api endpoint/tool function with valid inputs verify the correct database update query is generated (e g , update updatepackages set channel = 'stable' where ) test with invalid inputs (missing params, invalid channel name) test authorization checks (mock auth) task s5 3 implement server dependency handling (optional) goal allow server to specify update dependencies details extend updatepackages table/metadata to include dependency info (e g , service v1 2 requires updater v1 1+) modify task s5 1 manifest generation to include the dependencies array in the response if applicable (ref fr srv 001) task s5 3 test unit test server dependency handling goal verify dependency information is included in the manifest details write unit tests modify task s3 1 test mock database queries including dependency data verify the dependencies field is correctly populated in the json response when dependencies exist for a package client task c5 1 implement client dependency handling goal install updates in the correct order details modify the update loop parse the dependencies array from the manifest (task c2 3) if dependencies exist, determine a valid installation order (e g , build a dependency graph, perform topological sort) to ensure dependencies are updated before the components that depend on them if a required dependency update is missing from the manifest, log an error and potentially skip the dependent update (ref fr upd 007 partial) task c5 1 test unit test client dependency handling goal verify correct update sequencing based on dependencies details write unit tests provide sample manifests with different dependency structures (simple, complex, circular should detect error) test the ordering function verify it produces a valid sequence or returns an error for impossible dependencies test the main update loop logic verify it calls install functions in the order determined by the sequencing logic phase 6 rollback implementation client task c6 1 implement component backup goal save the current version before overwriting details implement function backupcomponent(targetpath, backuppath string) error before calling task c4 3 (replacecomponentfiles), copy the contents of targetpath to backuppath (e g , /backup/\<component name>/\<version>) use recursive copy, preserving permissions ensure backup directory has restricted permissions (task c8 10) handle errors during backup (ref fr cmp 002) task c6 1 test unit test component backup goal verify backup directory creation and file copying details write unit tests mock file system operations test that the correct source path is copied to the correct destination backup path verify permissions are set on the backup directory (mock os chmod) test error handling (source not found, destination write error) task c6 2 implement rollback trigger detection goal identify all failure conditions requiring rollback details in the main update workflow, add checks after specific operations after task c3 2 (hash fail), c3 5 (sig fail), c4 1 (disk space fail), c7 3 (stop fail), c4 3 (file op fail), c4 6+c7 5 (start/health check fail), c7 2 (self update fail) if any of these return an error designated as critical, call the central rollback function (task c6 4) (ref fr rbk 001 triggers) task c6 2 test unit test rollback trigger detection goal verify that specific errors correctly trigger the rollback function details write unit tests for the main update workflow mock the functions for each step (download, verify, stop, replace, start) make mocks return specific errors defined as rollback triggers verify that the performrollback function (mocked) is called when these specific errors occur, and not called when non critical errors or success occurs task c6 3 implement file restoration from backup goal restore the previously backed up version details implement function restorecomponent(backuppath, targetpath string) error first, delete the contents of targetpath (os removeall) then, copy contents from backuppath back to targetpath handle errors during restore (ref fr rbk 001 procedure step 3) task c6 3 test unit test file restoration goal verify restoration from backup directory details write unit tests mock file system operations create mock backup and target directories test that os removeall is called on the target path test that files are copied correctly from backup to target test error handling (backup path not found, target delete error, target write error) task c6 4 implement central rollback procedure goal orchestrate the rollback steps details create function performrollback(componentname, targetpath, backuppath string, triggererrorcode int) error this function calls task c7 3 (stop), task c6 3 (restore), task c4 6+c7 5 (start & verify rollback health check) log the trigger reason (using error code) and the success/failure of the rollback attempt itself (ref fr rbk 001 procedure) task c6 4 test unit test rollback procedure goal verify the sequence of operations during rollback details write unit tests mock dependent functions (stopcomponent, restorecomponent, startcomponent, healthcheck) verify that the functions are called in the correct order (stop > restore > start > healthcheck) test that the trigger error code is logged test return value based on success/failure of mocked functions task c6 5 implement transactional rollback for sequences goal roll back all successful updates in a failed sequence details modify the update loop that iterates through components needing updates maintain a list of components successfully updated in the current run if performrollback (task c6 4) is called for component b, iterate through the list of previously succeeded components (e g , a) in reverse order and call performrollback for each of them as well clear the success list after the sequence completes or fails (ref fr upd 007) task c6 5 test unit test transactional rollback goal verify that failures in a sequence trigger rollback of preceding successful updates details write unit tests for the multi component update loop mock the update process for individual components simulate a scenario update a succeeds, update b fails (triggering rollback) verify that performrollback is called for b and for a simulate scenario where all succeed; verify no extra rollbacks occur task c6 6 implement backup cleanup goal remove old backup after successful update details after task c7 5 (restart verification & health check) succeeds for a component, call os removeall on the corresponding backuppath created in task c6 1 (ref fr cmp 006) task c6 6 test unit test backup cleanup goal verify backup directory is removed on success details write unit tests mock os removeall call the cleanup function after simulating a successful update verify os removeall was called with the correct backup path task c6 7 implement rollback failure handling goal log critical errors if rollback itself fails details if task c6 4 (performrollback) returns an error (e g , restore failed, or restart/verify of the rolled back version failed), log this as a critical failure using a specific error code (task c8 4) update status reporting (task c8 7) to indicate critical failure (ref fr rbk 002) task c6 7 test unit test rollback failure handling goal verify critical logging and status update on rollback failure details write unit tests mock performrollback to return an error verify that a critical error is logged with the correct error code verify that writestatus (mocked) is called with a status indicating critical rollback failure phase 7 self update & specific component handling client task c7 1 implement self update mechanism goal allow the updater to update itself details implement the chosen strategy (e g , rename launch replace) download new binary to updater new backup current updater to updater old execute updater new with a flag (e g , self update stage2) current process exits new process ( self update stage2) replaces original updater binary with itself, restarts the service registration to point to the correct path, performs health check (task c7 2), and cleans up updater old implement checks on startup to detect and resume/cleanup incomplete self updates (e g , if updater new or updater old exist) (ref fr sup 001, fr sup 002) task c7 1 test unit test self update mechanism goal verify the steps involved in self update (rename, launch, replace) details write unit tests (challenging due to process replacement) focus on testing the functions responsible for each step downloading to new, backing up to old, launching the new process (mock os/exec), replacing the binary (mock os rename), cleaning up old test the startup logic that checks for new/ old files to handle interrupted updates task c7 2 implement self update rollback goal recover if the new updater binary is faulty details in the self update stage2 logic (task c7 1), perform a basic health check (e g , load config, initialize logging) if this fails, rename updater old back to updater, restart the service with the old binary, log the failure, and exit (ref fr sup 003, fr rbk 001 trigger) task c7 2 test unit test self update rollback goal verify rollback logic if the new binary fails its health check details write unit tests for the stage 2 logic simulate a health check failure verify that the code attempts to rename updater old back to updater (mock os rename) and restart the service (mock service control) task c7 3 implement full graceful stop goal stop components cleanly before forceful termination details enhance task c4 5 (stopcomponent) implement the sequence send sigterm/service stop/wm close wait (e g , time sleep) for a configurable timeout (e g , 30s), checking if the process exited if still running, send sigkill/terminateprocess return error only if the process still exists after the force attempt (ref fr cmp 001) task c7 3 test unit test graceful stop goal verify the graceful stop sequence (term/stop > wait > kill/terminate) details write unit tests mock os specific process control functions test cases process exits after initial signal, process requires forceful termination after timeout verify correct signals/commands are sent and wait logic is applied test error handling if signals fail task c7 4 \[decision needed] define & implement component health checks goal verify components are functional after update/rollback details for each component (service, ui/app, probe), define the health check method (e g , check pid existence, connect to a local health check tcp port, run \<component> healthcheck cli command, check for a heartbeat file) implement the check logic in the updater task c7 4 test unit test component health checks goal verify the implementation of each defined health check method details write unit tests for each health check function mock dependencies (e g , mock pid checks, mock tcp connection, mock cli command execution) test cases healthy component passes check, unhealthy component fails check, error during check returns error task c7 5 implement restart verification with health check goal confirm component started and is healthy details enhance task c4 6 (startcomponent) after initiating the start, call the component specific health check (task c7 4) in a loop for a defined timeout period (e g , 60 seconds) return success if health check passes within timeout, otherwise return error trigger rollback on error (ref fr cmp 005, fr rbk 001 trigger) task c7 5 test unit test restart verification goal verify the loop checking for health after start, including timeout details write unit tests mock the startcomponent initiation and the healthcheck function test cases health check passes immediately, health check passes after a few tries within timeout, health check fails consistently until timeout (should return error) task c7 6 implement ui/app update handling goal handle updates for user session processes carefully details before updating the ui/app component, implement os specific logic to attempt detection of active processes associated with that component running under user sessions (this is best effort) if detected, attempt graceful stop (task c7 3) proceed with the update regardless of whether the process stopped cleanly, but do not stop unrelated services (ref fr cmp 007) task c7 6 test unit test ui/app update handling goal verify detection of ui process and attempt to stop it details write unit tests using build tags mock os specific process detection logic test cases ui process not running (stop not called), ui process running (verify graceful stop is attempted) phase 8 advanced features & polish client task c8 1 implement "update now" trigger goal allow immediate, externally triggered updates details add checknow flag handling (task c1 5) that triggers the main update check sequence or/and implement an ipc listener (e g , unix domain socket, named pipe) that listens for a command ensure the listener/cli requires appropriate permissions (root/system) or authentication from the caller (e g , main commandit service) (ref fr upd 001b) task c8 1 test unit test "update now" trigger goal verify the trigger mechanism initiates an update check details write unit tests for cli modify task c1 5 test to verify checknow flag triggers the main update function (mocked) for ipc mock the listener and simulate receiving the command; verify the update function is called test permission/authentication checks for the trigger task c8 2 implement concurrency control goal prevent multiple update processes running simultaneously details at updater startup, attempt to acquire a system wide named mutex (windows createmutex) or create a lock file (e g , using gofrs/flock on /var/run/commandit updater lock or %programdata%) if lock acquisition fails (already held), log a message and exit immediately ensure the lock is released on normal exit or using defer handle interaction with checknow trigger if an update is already in progress (e g , log "update already running" and exit) (ref fr upd 009) task c8 2 test unit test concurrency control goal verify lock acquisition and release logic details write unit tests mock mutex/file locking functions test cases first instance acquires lock successfully second instance fails to acquire lock and exits verify lock is released on successful completion or error (using defer) test interaction with checknow when lock is held task c8 3 implement component reinstall logic goal allow forced reinstallation of a component details add flag reinstall \<component name> parse the flag trigger logic fetch latest manifest (task c2 1 c2 3) find the specified component download/verify package (task c3 1, c3 2, c3 5) stop component (task c7 3) delete the existing component directory (os removeall, respecting preservation rules from task b3 1/c4 3) extract package (task c4 2) start component (task c4 6+c7 5) update local manifest (task c4 4) (ref fr rin 001, fr rin 002) task c8 3 test unit test reinstall logic goal verify the sequence of operations during reinstall details write unit tests mock dependent functions (download, verify, stop, remove dir, extract, start, write manifest) simulate reinstall flag verify functions are called in the correct order verify os removeall is called on the target directory task c8 4 \[decision needed] define standard error codes goal create a consistent set of error identifiers details define an enum or constants (const errorcodenetworkfailure = 1001, errorcodehashmismatch = 2001, etc ) covering all expected failure scenarios identified in rollback triggers (fr rbk 001) and other operations document these codes (ref tr err 001) task c8 5 integrate error codes into logging goal use standard codes in logs for easier parsing details refactor all error logging points (task c1 3) to include the relevant error code (from task c8 4) as a structured field (e g , slog error("update failed", "errorcode", errorcodehashmismatch, "err", err)) task c8 5 test unit test error code logging goal verify error codes are included in structured logs details write unit tests capture log output simulate various error conditions verify the corresponding error code (from task c8 4) is present as a field in the json log output for error messages task c8 6 \[decision needed] define standard status codes goal create identifiers for operational states details define an enum or constants (const statusidle = 0, statuschecking = 1, statusdownloading = 2, statusfailedrollback = 99, etc ) covering the states listed in fr sta 001 document these codes task c8 7 implement status reporting goal provide machine readable current status and potentially update central db details define a status struct containing fields from fr sta 001 implement function writestatus(status status) that updates the status struct fields (using codes from task c8 6, c8 4) and writes it atomically (write to temp, rename) to the defined os specific location (e g , json file, registry, plist) additionally, consider if the updater should make an api call to update relevant fields in the central devices table (e g , agent updater version, agent last health check, agent health status, agent health details) after successful checks or updates (ref fr sta 001) task c8 7 test unit test status reporting goal verify status file/registry writing and potential api call details write unit tests mock file system/registry writing functions verify atomic write sequence (temp + rename) verify the content written matches the provided status struct and uses defined codes (task c8 6, c8 4) if implementing api call mock the http client and verify the correct api endpoint is called with the expected payload containing status information task c8 8 implement log rotation goal prevent log files from growing indefinitely details integrate a library like gopkg in/natefinch/lumberjack v2 with the logger setup (task c1 3) configure max size (mb), max backups, max age using values loaded from config (logmaxsizemb, logmaxfiles) (ref fr log 002, fr cfg 001) task c8 8 test unit test log rotation goal verify log rotation library integration details write unit tests (may require integration testing or careful mocking) test the logger initialization ensures the rotation library is configured with parameters from the config file simulating actual rotation in a unit test is difficult, focus on configuration task c8 9 implement secure config file permissions goal protect configuration from tampering details after creating the initial config file (task c4 7) or updating it, use os chmod (linux/mac) or windows security apis to set permissions restricting read/write access to system/root only (e g , 0600) (ref fr cfg 004, fr bst 003) task c8 9 test unit test secure config permissions goal verify correct permissions are set on the config file details write unit tests mock os chmod or windows security apis verify the function is called with the correct file path and permission mode (0600) after file creation/write task c8 10 implement secure permissions for other files goal protect logs, backups, and temporary files details ensure log files (task c1 3), backup directories (task c6 1), and temporary download/extraction directories (task c3 1, c4 2) are created with permissions restricting access appropriately (e g , readable only by system/root) (ref nfr sec 007) task c8 10 test unit test secure file/dir permissions goal verify permissions on logs, backups, temp dirs details write unit tests mock file/directory creation functions (os mkdirall, logger file creation) verify permissions are set correctly during creation (e g , using appropriate mode arguments or subsequent chmod calls) server task s8 1 implement api rate limiting goal protect the server from excessive requests details add rate limiting middleware to the http server (task s1 2) use a library like golang org/x/time/rate or framework specific middleware configure limits (e g , 10 requests/minute/ip) and potentially different limits based on the auth identifier (nfr srv 010) return http 429 too many requests when limits exceeded (ref nfr srv 009) task s8 1 test unit test rate limiting middleware goal verify rate limiting prevents excessive requests details write unit tests for the middleware simulate multiple requests from the same source (ip/auth id) verify that requests within the limit receive success codes, and requests exceeding the limit receive http 429 test different limit configurations task s8 2 implement detailed audit logging goal record comprehensive server activity logs details enhance server logging (task s2 4) ensure all fields specified in nfr aud 001 are logged for each relevant event (api request, package upload, promotion) use structured json format log to a file or central logging system (ref nfr aud 001) task s8 2 test unit test detailed audit logging goal verify all required audit fields are logged details write unit tests capture log output simulate various server events (api calls, admin actions) verify log entries contain all fields specified in nfr aud 001 with correct values based on the simulated event task s8 3 implement structured json error responses goal provide consistent error information to clients details define a standard json error struct ({"error code" " ", "message" " "}) create a utility function to generate http responses with this json body and appropriate http status codes (4xx, 5xx) use this function in all api error handling paths (ref eh srv 001) task s8 3 test unit test structured error responses goal verify api errors return the standard json structure details write unit tests using net/http/httptest simulate error conditions in api handlers (e g , invalid input, internal error) verify the response status code is correct (4xx/5xx) and the response body matches the defined json error structure with appropriate error code/message phase 9 security hardening & finalization client & server task cs9 1 \[decision needed] define & implement public key update mechanism goal allow secure rotation of the client's verification key details design the process (e g , new key package signed by both old and new keys, or a multi stage update) implement the client logic to handle this special update package and securely replace the stored public key (task c3 4) implement server logic to generate and serve this special package (ref nfr sec 006) task cs9 1 test unit test public key update goal verify client correctly handles key update packages and server generates them details write unit tests client mock server response with a key update package verify client correctly identifies it, verifies signatures (potentially old and new), and updates the stored key (mock storage) server test the logic for generating the special key update package (e g , signing with multiple keys) task cs9 2 conduct security reviews goal identify and fix potential security vulnerabilities details perform manual code reviews focusing on authentication, signature verification, hash checking, file system interactions (path traversal, toctou), permissions, ipc security, dependency vulnerabilities run static analysis tools (gosec) task cs9 3 perform thorough testing goal ensure functionality, resilience, and correctness details write unit tests for key functions (verification, parsing, etc ) develop integration tests simulating client server interaction for various scenarios (update available, no update, specific channel, auth fail) develop end to end tests install bootstrap, trigger scheduled/forced checks, simulate network errors, simulate verification failures, simulate install failures, verify rollback, verify self update, test concurrency verify relevant fields in devices table (agent versions, status) are updated correctly check agentupdatestatuslog entries (ref nfr tst 001, nfr tst 002, release criteria) task cs9 4 finalize api documentation goal provide clear documentation for the server api details generate/update openapi (swagger) specification file covering all v1 endpoints (/v1/check, admin endpoints if any), including request/response schemas, authentication methods host the documentation (ref tr api 001) task cs9 5 finalize internal documentation goal document design decisions and operational details details create/update readmes document the defined error codes (task c8 4), status codes (task c8 6), package structure (task b3 1), key management process (task b3 3, cs9 1) add code comments explaining complex logic document interaction with devices table fields task cs9 6 evaluate/implement certificate pinning (client) goal mitigate mitm attacks (optional hardening) details research go libraries/techniques for certificate pinning with net/http evaluate the trade offs (security vs operational complexity of key rotation) if approved, implement pinning against the updates commandit com certificate public key(s) (ref nfr sec 005) task cs9 6 test unit test certificate pinning goal verify certificate pinning prevents connections to servers with untrusted keys details write unit tests (if implemented) mock http client transport test cases connection succeeds with correctly pinned key connection fails with incorrect/unpinned key test handling of key rotation scenarios if applicable