Skip to content

feat: list firmwares endpoint#86

Merged
paragmore merged 1 commit into
tetherto:developfrom
tekwani:feat/list-firmwares
Jun 1, 2026
Merged

feat: list firmwares endpoint#86
paragmore merged 1 commit into
tetherto:developfrom
tekwani:feat/list-firmwares

Conversation

@tekwani

@tekwani tekwani commented May 31, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@paragmore paragmore merged commit 6d1f48d into tetherto:develop Jun 1, 2026
6 checks passed
paragmore added a commit that referenced this pull request Jun 9, 2026
* Feature - Site status live api (#4)

* feat: add API v2 endpoints (finance, pools, pool-stats, pool-manager) (#11)

* feat: add GET /auth/finance/energy-balance endpoint

Add energy balance API endpoint that aggregates power consumption,
pool transactions, BTC prices, and production costs into a unified
time-series response with period-based aggregation (daily/monthly/yearly).

Includes shared infrastructure: period.utils, constants for RPC methods,
worker types, aggregation fields, and utility functions (getStartOfDay,
safeDiv, runParallel).

* feat: add GET /auth/pools/:pool/balance-history endpoint

Add pool balance history API endpoint that fetches pool balance
snapshots via tailLog RPC, groups them into time buckets (1D/1W/1M),
and returns time-series data with balance and revenue per bucket.

* tiny improvements

* feat: add GET /auth/finance/ebitda endpoint

Add EBITDA API endpoint that aggregates pool transactions, power/hashrate
data, BTC prices, production costs, and block data to calculate selling
and HODL EBITDA metrics with period-based aggregation.

Includes shared infrastructure: period.utils, constants, and utility
functions required for finance endpoints.

* feat: add GET /auth/finance/cost-summary endpoint

Add cost summary API endpoint that aggregates production costs, BTC
prices, and power consumption to calculate energy and operational cost
breakdowns with period-based aggregation.

* feat: add GET /auth/pools endpoint

Add pools API endpoint that aggregates pool device lists and stats
from ORK clusters, supports mingo-based filtering, sorting, and
field selection, and returns pool summary with totals.

* feat: add GET /auth/pool-stats/aggregate endpoint

Add pool stats aggregate API endpoint that fetches pool stats history
and transactions, processes daily stats and revenue, and aggregates
by period (daily/weekly/monthly) with optional pool filtering.

* Fix costs bugs

* feat: add curtailment, operational issues, and power utilization to energy-balance

- Add ELECTRICITY worker type, ENERGY_AGGR/ACTIVE_ENERGY_IN/UTE_ENERGY aggr fields,
  and GLOBAL_CONFIG RPC method to constants
- Add 3 new parallel RPC calls: electricity stats-history (active_energy_in,
  ute_energy) and getGlobalConfig (nominalPowerAvailability_MW)
- Calculate curtailmentMWh, curtailmentRate, operationalIssuesRate, and
  powerUtilization per log entry
- Add avgCurtailmentRate, avgOperationalIssuesRate, avgPowerUtilization to summary
- Fix getProductionCosts to use ctx.globalDataLib instead of direct Hyperbee access
- Fix processCostsData to return daily costs (energyCostPerDay, operationalCostPerDay)
- Update tests to match new cost format and globalDataLib mock

* feat: remove block data, fix costs processing, add site param to ebitda

- Remove block data RPC call and processBlockData (not in spec)
- Remove blockCount, difficulty, ebitdaMarginSelling, ebitdaMarginHodl from log
- Fix processCostsData to handle flat objects from globalDataLib with daily costs
- Replace direct globalDataLib.getGlobalData range query with getProductionCosts helper
- Add site query param to schema, cache key, and handler for site-specific costs

* feat: fix costs processing and add site param to cost-summary

- Fix processCostsData to handle flat objects from globalDataLib with daily costs
- Replace direct globalDataLib range query with getProductionCosts helper
- Add site query param to schema, cache key, and handler for site-specific costs
- Update tests to match new cost format

* feat: add hashrate and remove snapshotCount from balance-history log entries

Align pool balance-history endpoint with API v2 spec which requires
balance, hashrate, and revenue time-series data.

* feat: remove snapshotCount from pool-stats-aggregate log entries

Align pool stats aggregate endpoint with API v2 spec which does not
include snapshotCount in the response.

* fix: use ext-data transactions instead of tail-log for pool stats aggregate

tail-log returns empty for type=minerpool. Switch to ext-data with
transactions key which has daily revenue and hashrate data. Also fix
changed_balance handling (values are BTC, not satoshis).

* fix: use ext-data transactions instead of tail-log for balance history

tail-log returns empty for type=minerpool. Switch to ext-data with
transactions key which provides daily revenue (changed_balance) and
hashrate (mining_extra.hash_rate). Also treat 'all' pool param as
no filter.

* fix: use ext-data stats array instead of list-things for pools endpoint

list-things for t-minerpool returns empty; pool data lives in ext-data
stats responses. Replaced flattenResults/flattenStatsResults/mergePoolData
with flattenPoolStats that parses the actual stats array format.

* code cleanup

* cleanup

* cleanup

* Ports pool manager from moria

* Removes regions concept to align with site-focused nature of API v2

* chore: remove comments from pool manager files

* Remove unncecessaey sute param and add integration tests

* removes site

* fix: remove site param from ebitda endpoint and add integration test

Data is fetched for a single site, so the site parameter is unnecessary.
Added security integration test for finance/ebitda endpoint.

* fix: remove site param from cost-summary endpoint and add integration test

Data is fetched for a single site, so the site parameter is unnecessary.
Added security integration test for finance/cost-summary endpoint.

* fix: rename filter to query param and use mingo projection for pools

Align with list-things pattern by renaming filter→query. Replace manual
sort and field filtering with mingo cursor methods for consistency.

* fix: move pool filter to RPC payload for balance-history endpoint

Pool name filter should be handled by the RPC worker, not filtered
client-side. The tx username is the account id.

* fix: move pool filter to RPC payload for pool-stats-aggregate endpoint

Pool name filter should be handled by the RPC worker, not filtered
client-side. The tx username is the account id.

* Address PR comments

* fix failing tests

* Removes tags from projections

* Fix integration tests

* requestRpcMapAllPages to fetch all pages from orks

* fix linting

* Fix failing tests

* fix: Improves user and roles ux (#12)

* return the created user

* fix: require users:r permission for GET /auth/roles/permissions

* fix: update getRolesPermissions route to require users:w permission

* fix: enhance getRolesPermissions to filter roles based on user role

* fix: update getRolesPermissions to exclude roleManagement for super admin

* Cleanup

* feat: add GET /auth/finance/subsidy-fees endpoint (#14)

* feat: add GET /auth/finance/subsidy-fees endpoint

Port Bitcoin network block data (subsidy rewards + transaction fees) from
legacy dashboard to API v2. Fetches HISTORICAL_BLOCKSIZES from mempool
worker, aggregates by period (daily/weekly/monthly).

* fix: remove unused site parameter from getProductionCosts

* Adding CI (#23)

* feat: add alerts API v2 endpoints (#24)

* resolve conflicts

* Feature: Alerts

* refactor: use RPC constants and explicit field mapping in alerts handlers

* Fix code smells

* fix failing tests

* Remove metrics

* Address comments

* feat: add metrics API v2 endpoints (#21)

* feat: add finance revenue and revenue-summary endpoints (#22)

* feat: add GET /auth/finance/revenue endpoint

Port pool transaction revenue data from legacy dashboard to API v2.
Separates revenue from pool fees, supporting both F2Pool (changed_balance
+ tx_fee) and Ocean (satoshis_net_earned + fees_colected_satoshis) formats.
Aggregates by period with optional pool filter.

* feat: add GET /auth/finance/revenue-summary endpoint

Most impactful endpoint — replaces 9 API calls + ~1500 LOC of frontend
processing. Merges transaction data, BTC prices, costs, power, hashrate,
block data, and electricity data into comprehensive daily rows with EBITDA,
production cost, hash revenue, curtailment, and power utilization metrics.

* fix: include pool name in worker type for revenue endpoint

* refactor: extract shared finance utils and consolidate duplicated logic

- Create finance.utils.js with shared utilities:
  - validateStartEnd: replaces duplicated validation in every handler
  - normalizeTimestampMs: moved from finance.handlers.js
  - processTransactions: consolidates processTransactionData and
    processEbitdaTransactions (fixes missing normalizeTimestampMs and
    incorrect BTC_SATS division bugs), supports trackFees option
  - extractCurrentPrice: merges flat and nested EBITDA price formats
  - processBlockData: extracted for reuse across revenue endpoints
- Refactor finance.handlers.js to use shared utils
- Add comprehensive unit tests for all utils (24 tests)
- Update handler tests to remove tests for deleted functions

* Remove spec doc

* feat: add device listing API v2 endpoints (#25)

* feat: add device listing API v2 endpoints

* fix: paginate listThings RPC and add field projections for device endpoints

Address PR review: use requestRpcMapAllPages to fetch all items beyond
the default 100-item RPC limit, and pass DEVICE_LIST_FIELDS projection
to reduce response size when status=1.

* fix: use requestRpcMapLimit with limit/offset and remove status

- Switch getMiners/getContainers from requestRpcMapAllPages to
  requestRpcMapLimit, passing limit/offset to RPC instead of
  fetching all objects
- Remove status:1 from all listThings calls as DEVICE_LIST_FIELDS
  don't have snap properties
- Update pagination test to verify RPC payload

* Add maximium to limit

* Remove /auth/miners

* Feat/add get configs route (#26)

* Add get configs route

* Add tests and lint

* Remove old pool manager apis (#29)

* feat: add GET /auth/finance/hash-revenue endpoint (#27)

* non rpc method calls to ork (#28)

* fix: address OWASP security review findings for v2 API endpoints (#30)

* ci: enforce coverage (#31)

* feat: pool config stats (#32)

* feat: pool config stats

* var name typo fix

* feat: add GET /auth/miners with getThingsCount (#33)

* fix: config routes read permissions fix (#34)

* ci: improve coverage summary (NYC table) (#35)

* feat: containers pool stats (#36)

* fix: add schema bounds to prevent negative limit/offset bypass (#37)

* ci: move away from pull_request_target (#38)

* feat: add groups stats endpoint and racks filter for metrics (#47)

* feat: add groups stats endpoint and racks filter for metrics

Add GET /auth/groups/stats endpoint for live rack-group aggregation
(efficiency, hashrate, power, miner counts). Extend hashrate and
consumption metrics with optional racks query parameter for filtering
by rack groups via ORK RPC.

* feat: add groups stats endpoint and racks filter for metrics

Add GET /auth/groups/stats endpoint for live rack-group aggregation
(efficiency, hashrate, power, miner counts). Extend hashrate and
consumption metrics with optional racks query parameter for filtering
by rack groups via ORK RPC.

* fix: rename racks filter to containers for metrics endpoints

* refactor: deduplicate parseContainers, extractKeyEntry and use AGGR_FIELDS constants

* fix: remove non-functional containers filter from hashrate/consumption

tailLogCustomRangeAggr RPC method does not support containers param,
so remove the dead code from getHashrate/getConsumption handlers,
their schemas, route cache keys, and related tests.

* fix: handle noAuth mode in capCheck

capCheck crashes in noAuth mode when routes pass permissions because
ctx.authLib is undefined. Add early return guard matching authCheck.

* Revert "fix: handle noAuth mode in capCheck"

This reverts commit 2d4d992.

* test: improve branch coverage for metrics handlers

Add tests for uncovered branches: temperature rolling avg,
container history prefix match, non-object guard branches,
and groupRange config paths in getPowerMode/getTemperature.

* chore: remove unnecessary comment

* Add new auth/cooling system api (#51)

* Add new auth/cooling system api

* Fix review comments, make the tag generic for dcs device and update endpoint path

* Fix

* remove device name

* fix

* fix: sanitize queryActions input to prevent injection and DoS (#49)

* fix: sanitize queryActions input to prevent injection and DoS (TDEBT-38)

Add maxLength constraints to suffix (200) and queries (10000) in route
schemas, validate queries array type and cap length at 50 in handler.

* fix: tighten queryActions limits and extract to constants

Reduce queries string maxLength from 10000 to 1000 and cap the array at
10 items (previously 50). Extract both limits to named constants.

* Add energy views endpoint support (#52)

* Add energy views endpoint support

* move outside to dir with other utils

* fix imports

* feat: microsoft oauth (#54)

* Support site overview endpoints for dcs and miner group wise overview (#55)

* Support site overview endpoints for dcs and miner group wise overview

* update move to site handlers

* Support new dcs device tags update and fix cooling system apis (#56)

* Support new dcs device tags update and fix cooling system apis

* update the attributes for rack group

* Tests

* tests

* Add hvac circuit 1 and layout api updates (#58)

* Add hvac circuit 1 and layout api updates

* Update hvac circuit2 api

* Add site effciency api (#57)

* Add site effciency api

* Add site effciency api routes

* tests

* Add explorer racks api (#59)

* (improvement) Explorer handlers, Racks list, Search filtering flow improved (#60)

* improv: workers/lib/server/handlers - explorer - 'filterBySearch' flow improved.

* improv: workers/lib/server/handlers - explorer - 'filterBySearch' flow & usage improved.

* fix: workers/lib/server/handlers - explorer - 'filterBySearch' flow fixed.

* test: tests/unit/handlers - explorer - 'filterBySearch' cases coverage extended.

* test: tests/unit/handlers - coolingSystem - 'createMockConfig' result generation fixed.

* feat: group hashrate by miner and container (#62)

* fix: finance v2 handler RPC regressions (#67)

* fix: processBlockData parses HISTORICAL_BLOCKSIZES flat-array shape

The mempool worker's getWrkExtData returns a flat array of block records
[{ts, blockSize, blockReward, blockTotalFees}, ...], but processBlockData
only handled nested .data/.blocks wrappers - it iterated entry's own field
names, Number('ts') returned NaN, and produced an empty daily map. The
SubsidyFee page then rendered "No data available".

Detect the flat shape (entry has .ts/.timestamp/.time) and process it
directly. Also surface blockSize on getSubsidyFees and getRevenueSummary
log entries (and totalBlockSize/avgBlockSize on the summary) - needed for
SubsidyFee's "Avg Fees in Sats/vByte" chart to render after this fix.

* fix: cost-summary propagates per-day btcPrice

Two compounding bugs in getCostSummary caused btcPrice=0 for every log
entry, leaving ProductionCostPriceChart's overlay line at 0:

1. Wrong RPC key. The handler queried mempool with key: 'prices', which
   the worker doesn't recognize and so returns the live snapshot
   ({currentPrice, blockHeight, ...}). Switched to 'HISTORICAL_PRICES',
   which returns [{ts, priceUSD}, ...].

2. processEbitdaPrices couldn't parse the production shape. Same class
   as the processBlockData fix (Bug C): the mempool worker returns a flat
   per-ORK array of records, not a wrapper. Detect when entry has
   .ts/.timestamp/.time and process it as the item directly; also accept
   priceUSD (the actual upstream field name) alongside price.

The processEbitdaPrices fix incidentally makes getRevenueSummary and
getHashRevenue use real per-day prices instead of falling back to
currentBtcPrice. getEbitda still uses the wrong key: 'prices' (line 344)
and is left for a follow-up.

* fix: processTailLogData drills into .val for nested TAIL_LOG_RANGE_AGGR

The TAIL_LOG_RANGE_AGGR RPC returns per-day items as
{ts, val: {site_power_w, hashrate_mhs_5m_sum_aggr}}, but
processTailLogData read item[AGGR_FIELDS.SITE_POWER] directly without
drilling into .val, so powerW and hashrateMhs were 0 for every entry.
RevenueSummary then showed 0 for Avg Power, Avg Hashrate, and Hashrate
Capacity Factor; EBITDA's per-day power/hashrate were similarly zeroed.

Mirror the .val/.flat fallback pattern that processConsumptionData
already uses (workers/lib/server/handlers/finance.handlers.js:172).

* fix: hash-revenue hashrate and network-hashrate populate from real RPC

Two bugs in getHashRevenue caused hashrateMhs and networkHashrateMhs
to be 0 for every log entry, leaving HashBalance entirely zeroed:

1. processHashrateData read item[AGGR_FIELDS.HASHRATE_SUM] directly,
   but TAIL_LOG_RANGE_AGGR wraps measurements as
   {ts, val: {hashrate_mhs_5m_sum_aggr}}. Same .val drilling fix as
   processTailLogData.

2. processNetworkHashrateData expected entries wrapped under .data,
   but the HISTORICAL_HASHRATE RPC returns a flat per-ORK array of
   {ts, avgHashrateMHs} records. Same flat-shape detection as
   processBlockData (Bug C).

* Fix memory leak in authCheck by implementing LRU caching and removing in-memory cache (#61)

* Support summary for grouped by in hashrate metrics api (#68)

* Support summary for grouped by in hashrate metrics api

* update groupKey

* fix: groups stats accepts rack ids and returns rack objects (#69)

* Add groupBy for metrics consumption api (#70)

* Update the cooling system handlers to fix flow readings (#71)

* fix(finance): correct energy-balance period aggregation (#72)

The shared aggregateByPeriod summed every numeric field, which is
correct for totals but produced nonsense for rates/means (curtailment
rate, btcPrice, sitePowerMW, etc.) on weekly/monthly buckets.

- Add an optional `meanKeys` arg to aggregateByPeriod that averages
  listed fields instead of summing. Default behavior is unchanged for
  the 6 existing callers.
- getEnergyBalance now passes meanKeys for sitePowerMW, btcPrice and
  the rate fields, then post-processes to recompute energyRevenue*_MW
  against the (correctly meaned) sitePowerMW denominator.
- Add sitePowerMW + energyRevenueBTC_MW/energyRevenueUSD_MW to log
  entries; add avgPowerConsumption + avgEnergyCostPerMWh +
  avgOperationalCostPerMWh to summary.
- Schema: add 'weekly' to the period enum.

* chore: facs version update (#73)

* Update the dcs apis to support the new tags (#74)

* develop sync (#76)

* feat: adopt JWT-based svc-facs-auth (#53)

* feat: forecast endpoints (#80)

* feat: add rack grouping to metrics/hashrate endpoint (#82)

Extend GET /auth/metrics/hashrate with `groupBy=rack` and an optional
`racks` CSV filter so charts can render a per-rack hashrate time series
for a specific set of racks.

- groupBy=rack reads the hashrate_mhs_5m_pdu_rack_group_sum aggregation
  from stat-1D, the same obj_concat aggregation family already used for
  type/container group grouping
- racks=group-1_rack-1,group-2_rack-1 narrows each log entry's hashrate
  object and the summary breakdown to the requested racks
- racks is cache-keyed and only applied when groupBy=rack

* feat: add rack grouping to metrics/consumption endpoint (#83)

Extend GET /auth/metrics/consumption with `groupBy=rack` and an optional
`racks` CSV filter, mirroring the rack grouping added to metrics/hashrate
in #82.

- groupBy=rack reads the power_w_pdu_rack_group_sum aggregation from
  stat-1D, the same obj_concat aggregation family already used for
  type/container group grouping
- racks=group-1_rack-1,group-2_rack-1 narrows each log entry's powerW
  object (and the derived consumptionMWh) and the summary to those racks
- racks is cache-keyed and only applied when groupBy=rack

* feat: work order + spare parts HTTP API (#79)

* feat: expose Work Order HTTP API + RBAC

Adds the Work Order HTTP surface as thin wrappers over the existing
things RPC plumbing:
  POST   /auth/work-orders                create  (registerThing)
  GET    /auth/work-orders                list    (listThings + type filter)
  GET    /auth/work-orders/:id            get     (listThings + id+type filter)
  PATCH  /auth/work-orders/:id            update  (updateThing)
  POST   /auth/work-orders/:id/close      close   (updateThing status=closed)
  POST   /auth/work-orders/:id/cancel     cancel  (updateThing status=cancelled)
  POST   /auth/work-orders/:id/assign     assign  (updateThing assignedTo)
  GET    /auth/work-orders/:id/audit      history (getHistoricalLogs)

Introduces a new RBAC resource work_order (r/rw) granted to
operator/admin/repair_technician roles for write and to viewer
roles for read. Strips the duplicated [HRPC_ERR]= prefix and
bubbles structured rack errors verbatim. Skips capCheck when the
gateway runs with --noauth so local curl-testing works through
permissioned routes.

* feat: searchable Work Order list with pagination envelope

Adds filter shortcuts (q, assignee, creator, partId, status, type,
from, to) to GET /auth/work-orders alongside the existing mingo
?query passthrough; q is a case-insensitive regex $or against code
and info.issue, the rest map to info.* paths and run on the rack
the same way every other list does. Pages now return the
{data, totalCount, offset, limit, hasMore} envelope by calling
listThings and getThingsCount in parallel, and every shortcut is
wired into the cache key so cached pages do not bleed across
filter combinations.

* feat: spare-part PUT gated by an open Work Order + repair history

Adds PUT /auth/spare-parts/:id which validates the supplied
workOrderId resolves to an open or in_progress WO, pushes the
underlying updateThing on the part rack with workOrderId injected
into info, and appends a denormalised entry to the WO's
partsMoves[] so the audit trail stays on the Work Order itself.
GET /auth/spare-parts/:id/repair-history mingo-queries every WO
that ever touched the part and returns each move row hydrated with
workOrderCode in the standard {data, totalCount, offset, limit,
hasMore} envelope.

* feat: Work Order log entries + file upload/download/delete routes

Adds POST /auth/work-orders/:id/log which forwards to the existing
saveThingComment RPC so the WO comments[] doubles as the work log.
Adds POST/GET/DELETE /auth/work-orders/:id/files routes backed by
@fastify/multipart on the gateway and the new
storeWorkOrderFile/loadWorkOrderFile/removeWorkOrderFile pass-
throughs on the ork; uploads validate mime + size, append metadata
to WO.info.files via pushAction, and reject mutations on closed or
cancelled WOs.

* feat: spare-part register flow + Type-1/Type-2 Work Order dispatch

POST /auth/spare-parts now creates the part and a paired Type-1 WO in
one call, returning {partId, workOrderId, workOrderCode}. POST
/auth/work-orders resolves the target part for both flows from
deviceIdentifier (id, code, serialNum, or macAddress) and rejects
unknown deviceTypes with ERR_INVALID_DEVICE_TYPE / unresolved parts
with ERR_PART_NOT_FOUND.

* feat: accept warranty payload on Work Order create/update

Adds an open `warranty: { vendor, fields }` shape to the create and
update body schemas; vendor-specific field validation lives in the
inventory worker so app-node stays agnostic of vendor differences.

* feat: GET /auth/work-orders/:id/export with PDF + CSV output

Export accepts either the WO uuid or its IVI-* code in the path and a
required ?format=pdf|csv|docx querystring. CSV flattens one row per
parts-movement entry (WO header columns repeated). PDF is server-rendered
via PDFKit and includes header, triage, work log, parts movements, file
references, and a vendor-specific warranty section. format=docx returns
501 with ERR_EXPORT_FORMAT_NOT_IMPLEMENTED until phase 2.

* refactor: ship CSV only; pdf + docx return 501 (deferred to FE/phase 2)

Drops the pdfkit dependency and the PDF renderer. The export endpoint
now serves CSV directly; pdf and docx both 501 with
ERR_EXPORT_FORMAT_NOT_IMPLEMENTED, keeping the route shape stable for
when the frontend renders PDF client-side.

* feat: align SPARE_PART_INITIAL_LOCATION to canonical 'Site Warehouse'

Mirrors the new MINER_LOCATIONS enum from the inventory worker.

* refactor: camelCase MINER_LOCATIONS values + SPARE_PART_INITIAL_LOCATION

Mirrors the inventory worker constant.

* feat: GET /auth/spare-parts with mingo-side location / status / q filters

Querystring shortcuts (location, status, q) translate to a mingo query
forwarded to the rack via listThings + getThingsCount — no app-node
post-filtering. q is a case-insensitive regex against code, info.serialNum,
and info.macAddress. WO things are excluded by default via type:{\$ne:...},
overridable by an explicit query.type. Cache key includes every filter
shortcut so combinations don't collide.

* refactor: extract escapeRegex, listThingsWithCount, stableJsonString to utils

Both list handlers (work-orders + spare-parts) hand-rolled the same
regex-escape + listThings/getThingsCount/pagination skeleton; collapses
to a single utils helper used by both. Cache keys for the two GET list
routes now canonicalize their JSON inputs via stableJsonString so
semantically-equal queries share a cache slot instead of missing each
other on key-order differences.

* refactor: drop waitForThing — registerSparePart returns action ids, no polling

App-node was polling listThings after each pushAction to surface the
rack-assigned thing code in the response — exactly the
'submit-and-poll-in-app-node' anti-pattern the codebase had already
rejected. registerSparePart now pre-generates partId/woId, fires both
registerThing pushActions in parallel, and returns
{partId, workOrderId, partActionId, workOrderActionId, errors}. Clients
read the eventually-assigned codes from GET /auth/actions/done/:id like
every other write in the app.

Removes waitForThing + sleep from utils and the two timeout constants
that only existed to tune it.

* refactor: address peer-review #3 #6 #8 #10 #12 #20

#3 (atomicity) — updateSparePart now checks the part pushAction's
   errors[] before firing the WO partsMoves append. If the part write
   was rejected at push time, throws ERR_PART_UPDATE_PUSH_FAILED:<msg>
   with a 502 instead of silently enqueueing the WO append. Response
   shape also gains partActionId / workOrderActionId / workOrderAppendErrors
   so the FE can detect a post-push WO failure and trigger a manual
   reconcile.
#6 (status casing) — WO status enum normalised to 'inProgress' so
   every info.* enum value follows the camelCase convention adopted
   for MINER_LOCATIONS.
#8 (registerSparePart field sprawl) — drops the
   info.model→info.deviceModel→'unknown' fallback chain and the
   serialNum→macAddress→partId fallback. deviceModel and serialNum
   are now both required up front with explicit ERR_*_REQUIRED errors.
#10 (action latency) — register/update responses include
   expectedActionLatencyMs sourced from ctx.conf.expectedActionLatencyMs
   (default 1000) so the FE can pace its /auth/actions/done/:id polling
   instead of guessing.
#12 (export 501) — error message now carries the requested format
   (ERR_EXPORT_FORMAT_NOT_IMPLEMENTED:pdf / :docx) so the FE can tell
   which format was rejected without re-reading the request.
#20 (pagination) — listThingsWithCount now slices the dedupe'd union
   down to the requested limit so multi-ork fan-out can't return more
   rows than the caller asked for. hasMore is now derived from
   offset + limit rather than offset + data.length. Multi-rack
   offset-pagination remains best-effort because each rack applies
   the offset locally; documented inline.

* revert: restore 'in_progress' in WO status schema enum

Mirrors the inventory rack revert — keeps existing 'in_progress' WO
records valid for transitions.

* revert: restore human-readable MINER_LOCATIONS values

Mirrors the inventory rack revert.

* refactor: call generic storeFile / loadFile / removeFile with file type

Updates the work-order file handlers to use the renamed generic file
RPCs and tags each call with FILE_TYPES.WORK_ORDER so the rack can
dispatch on it.

* fix: pass workOrderId + fileId to scoped file RPCs, surface blobCleared

loadFile / removeFile are now called with { workOrderId, fileId } so the
rack resolves the blob descriptor from the work order it belongs to —
app-node no longer forwards a raw blobRef. deleteWorkOrderFile surfaces
the rack's { cleared } result as blobCleared so the HTTP caller can tell
whether the underlying blob was actually removed.

* refactor: address PR #79 review feedback

- resolve the work_order rack from the ork rack registry via listRacks
  (getWorkOrderRackId, cached on ctx) and drop the workOrderRackId config
  key — the rack id is discovered, not deployment config
- relocate submitWorkOrderAction out of generic utils into the new
  server/lib/workOrders module alongside getWorkOrderRackId
- add WORK_ORDER_TERMINAL_STATUSES constant, replacing the duplicated
  ['closed', 'cancelled'] literals across the WO handlers
- workOrderExport: derive the CSV header and rows from one [name,
  extractor] schema instead of two hand-synced lists
- rename pushOne -> pushSingleAction in registerSparePart

* refactor: derive WO export CSV columns from json keys

renderWorkOrderCsv builds the header from the work order's own properties
— top-level code plus every info field, then each parts-movement entry's
keys — so the CSV tracks the worker response schema with no hand-kept
column list. Drops the CSV_HEADERS / WO_COLUMNS / MOVE_COLUMNS definitions.

* refactor: remove non-functional comments from WO export and rack helpers

* refactor: promote _csvEscape to a generic csvEscape util

* refactor: rename WO and spare-parts modules to dot-separated file names

Align the work order and spare parts file names with the repo convention
(cooling.system.routes.js, energy.system.routes.js, etc.): camelCase
basenames become dot-separated — spareParts.handlers.js ->
spare.parts.handlers.js, workOrders.js -> work.orders.js,
workOrderExport.js -> work.order.export.js. Updates every require() path,
route registration in index.js, and test references.

* (fix) NPM audit, Dependencies invulnerability fixed (#84)

* chore: root - package-lock - dependency tree updated.

* fix: root - package-lock - dependency tree packages invulnerability fixed.

* feat: list firmwares endpoint (#86)

* feat: miner log download via Hypercore P2P streaming (#85)

* feat: add miner log download REST endpoints and unit tests

* add LogDownloader for P2P miner log streaming

Introduces a LogDownloader class that fetches miner log files directly
from wrk-miner via Hypercore/Hyperswarm, bypassing the HRPC pipeline.
Wired up in the http worker after facilities are ready.

* trim verbose comments in log download handlers

* Fix LOGS_PEER_NOT_FOUND

* feat: forecast history endpoint (#87)

* feat: forecast settings (#89)

* feat: forecast settings

* get forecast settings endpoint

* fix: add info params + fix WO auth (#88)

* feat: add info params (notes, remarks, site, location) to work order schema

Accept optional info object with notes, remarks, site, and location
on POST /auth/work-orders and PATCH /auth/work-orders/:id. The handler
merges these into the thing info alongside the top-level fields.

* fix: auto-qualify bare permission names in tokenHasPerms

tokenHasPerms received bare resource names (e.g. 'work_order') from
route perms, but _permsMatch expects 'resource:level' format. Splitting
a bare name by ':' left `required` as undefined, crashing on spread.

* Chore/main sync (#91)

* Ci pr trigger change main (#39)

* chore: package json updates for publishing (#41)

* chore: package json updates for publishing

* update deps

* ci: package publishing (#40)

* ci: adding release pr process and version bump (#42)

* Release: v1.0.0 (#44)

* ci: release pr local jobs (#46)

* ci: persistents credentials to allow tag creation (#48)

* Release: v1.0.0 (#50)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore: facs version update (#77)

* refactor: logs cleanup (#78)

* ci: CI Checks — dependency review, audits, and workflow improvements (#81)

- Introduce security dependency review on pull requests
- Improve audit reporting (dependency review, npm/pnpm audit, audit-ci on core)
- Improve overall CI checks: single install + node_modules cache, lockfile gate, parallel jobs, summary

Fleet: core. Suggested PR title matches commit subject.

* reset ci updates

---------

Co-authored-by: andretetherio <andre.mendes@tether.io>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: Parag More <34959548+paragmore@users.noreply.github.com>
Co-authored-by: Caesar Mukama <mcaesar88@gmail.com>
Co-authored-by: andretetherio <andre.mendes@tether.io>
Co-authored-by: borik91 <9007515+boris91@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants