- improved
Tool tracking now reachable from every shipped surface
The tool tracking module had been shipped for many iterations but wasn't reachable from the in-app navigation — /tools, /tools/[id], and /tools/new existed but the only paths in were deep links and dashboard-card click-throughs. This bundle wires it into every entry point a user actually uses: top nav gains a Tools link (between Mechanic and Map); the global ⌘K search palette fans out to a new /api/search/tools endpoint and returns tools alongside assets with a Tool badge; the /dashboard quick-actions strip adds a Tools button between Log hours and Add asset; the /mechanic role page (where mechanics live) adds a prominent safety-tinted Tools button at the top of its action strip; the homepage hero gets a one-line callout placing tool tracking next to the hardware-tracker mention; /yards now displays "N assets · M tools" per yard (filtered to non-RETIRED); and the /tools empty state explains the module instead of just saying "no tools yet." 7 new contract tests for the tools search helper.
- new
GET /tools/{id}/qr — print-ready QR codes for label printers
Public REST API now exposes the same QR-generation surface the in-app UI uses. Returns a 600px PNG by default (or SVG with ?fmt=svg; ?size=N clamps 120-2000) encoding a deep-link to /scan/{scanToken}. Error correction Level H so the code stays scannable with up to ~30% of the surface obscured (real-world: dirt, scratches, partial damage). Designed for the loop "pull the tool roster, generate a label per row, batch-print to the Zebra / Brother / Dymo" — no more screen-scraping the in-app surface. Scope: tools:read. Cross-tenant safe (404 on tools the org doesn't own).
Learn more → - new
Status transitions now audited: PATCH /tools/{id} status moves emit AUDIT
Flipping a tool's status — GOOD → NEEDS_ATTENTION, anything → RETIRED, anything → MISSING — previously wrote silently to the DB with no row in /tools/{id}/events, so asking the events feed "when did this tool retire?" produced nothing. updateTool() now emits an AUDIT ToolEvent with a structured `status_changed: from=X to=Y` description prefix whenever the status enum actually changes. Same `assignment_changed:`-style pattern; no-op on same-value patches; best-effort emission (won't fail the update if the event log write rejects). 6 new contract tests cover GOOD→RETIRED, GOOD→MISSING, BROKEN→GOOD, no-emit on unchanged, no-emit on non-status patches, actorId fallback to null on system paths, and failure recovery.
Learn more → - new
Tool creation now shows up in the events feed
GET /api/v1/tools/{id}/events previously skipped the moment of creation — the feed only contained CHECK_OUT / CHECK_IN / ASSIGNMENT / FAILURE_REPORT / AUDIT (stock + PM) entries. Now createTool() emits an AUDIT row with a `tool_created: name=... category=... consumable=true` structured prefix so consumers paginating the feed see the full lifecycle from row zero. Best-effort emission (the create still succeeds if the event log write rejects). 6 new contract tests cover the prefix shape, consumable flag, actor=null bulk-import path, validation-failure no-emit, and best-effort failure recovery.
Learn more → - new
Dashboard widget: warranties expiring in the next 60 days
The warrantyExpiringTools() rollup helper from the previous iter now has a UI surface. ToolWarrantyExpiringCard renders the soonest-to-expire tools (max 5 inline + a `see all` link) on /dashboard, so fleet managers and accountants spot warranty risk at the same glance as low-stock and PM-overdue. Card returns null when nothing's in the 60-day window — a clean dashboard means no work. 4 new tests for the formatDaysUntilExpiry helper cover singular/plural/zero/fractional/negative inputs.
- new
Warranty-expiring filter: GET /tools?warrantyExpiringDays=N
Tool.warrantyEndDate has been part of the schema since v1 but nothing surfaced it. GET /api/v1/tools now accepts ?warrantyExpiringDays=N (1-365) to surface tools whose warranty expires within the next N days — excludes already-expired warranties and tools without a date so the result is actionable. Composes with the existing CSV export (?warrantyExpiringDays=60&format=csv) for renewal-planning spreadsheets. Same filter on the in-app /api/tools route. New isWarrantyExpiring() predicate + warrantyExpiringTools() org-wide rollup helper (ordered by warrantyEndDate ASC so soonest-to-expire surfaces first) for any dashboard widget. 9 new tests cover the predicate boundaries, the rollup DB call shape, and the out-of-range no-op.
Learn more → - new
tool.created webhook (14th event type)
POST /api/v1/tools and POST /api/v1/tools/batch now fire a tool.created webhook for each new row. Mirror of asset.created — accounting / asset-register integrations no longer need a nightly reconciliation pass to discover new tools. Payload carries the toolId, name, category, isConsumable, the auto-generated scanToken (so receivers can render the QR/NFC label immediately at creation), optional purchaseCost (useful to prime depreciation), and the actorId (null on bulk-import paths). Best-effort delivery (won't fail the create if enqueue rejects). 4 new contract tests cover full-field passthrough, bulk-import actorId=null, validation-failure no-emit, and best-effort failure recovery. Zapier integration page goes from eleven to twelve tool/fleet events; webhook docs hero updates from thirteen to fourteen.
Learn more → - new
tool.serviced webhook (13th event type) + OpenAPI mark-serviced spec
POST /api/v1/tools/{id}/mark-serviced now fires a tool.serviced webhook alongside the internal AUDIT ToolEvent. Payload carries previousLastServicedAt (null on first service), newLastServicedAt, the pmIntervalDays in effect at service time, the actorId, and any free-form note — depreciation systems, OEM warranty trackers, and CMMS exports subscribing to it no longer have to poll the events feed for PM completions. Best-effort emission (won't fail the service record if delivery enqueue rejects). Same iteration also adds the previously-undocumented mark-serviced endpoint to /openapi.yaml — until now it shipped in code (iter 86) but had no OpenAPI definition, so codegen consumers couldn't see it. 5 new contract tests cover success, previous=null on first service, no-emit on 404, no-emit on 422 (missing pmIntervalDays), and best-effort failure recovery. /docs/api/webhooks + /integrations/zapier both surface the new event; Zapier headline goes from ten to eleven tool/fleet events.
Learn more → - new
tool.assignment_changed webhook (12th event type)
When a tool's owner moves (assignedUserId / assignedVehicleId / assignedYardId / parentKitId), the same PATCH that emits the internal ASSIGNMENT ToolEvent now also fires a tool.assignment_changed webhook. A single PATCH that touches multiple assigned* fields produces one delivery whose `changes` array enumerates each kind that moved — accounting / HR systems mirroring tool ownership no longer have to poll the events feed. Best-effort emission (won't fail the PATCH if delivery enqueue rejects). 5 new contract tests cover single-field emission, multi-field aggregation, no-emit on no-op PATCH, no-emit on unchanged values, best-effort failure recovery, and ISO timestamp shape.
Learn more → - improved
Tool tracking now visible across pricing + role pages
Pricing, /for-mechanics, and /for-managers now each carry a dedicated tool-tracking section so visitors land on the right framing for their role. /pricing flags tools as in-core ('built-in, not a paid add-on') beside the optional-hardware section. Mechanics page emphasizes the shop side: kit checkout, low-stock alerts on consumables, PM on power tools. Managers page emphasizes the analytics side: checkout utilization, low-stock dashboard cards, fleet tool book value. All routes link back to /product/tool-tracking for the full detail.
Learn more → - new
Events feed gains actorId + linkedAssetId filters
GET /api/v1/tools/{id}/events now accepts ?actorId= and ?linkedAssetId= to narrow the audit feed. Pairs naturally with the existing kind + since + cursor filters: 'show me every CHECK_OUT event Tom made on the JD this quarter' is one query. 3 new contract tests cover passthrough + composition with kind.
Learn more → - new
Assignment changes now audited: ASSIGNMENT ToolEvent on every move
PATCH /api/v1/tools/{id} (and the in-app PATCH) now emit an ASSIGNMENT ToolEvent each time assignedUserId, assignedVehicleId, assignedYardId, or parentKitId changes. The description uses a structured 'assignment_changed: type=X from=A to=B' prefix so audit consumers parse the move directly out of the events feed (iter 88) without joining the Tool table. The ASSIGNMENT ToolEventKind was declared in the enum from v1 but never emitted — this closes that gap. Same-value PATCHes don't emit (no no-op events). 8 new tests cover single + multi-field changes, no-emit on unchanged, kit transitions, null-side rendering, fallback when actorId is unset (CSV import path), and best-effort failure recovery.
Learn more → - new
Paginated audit-event feed: GET /api/v1/tools/{id}/events
Stream a tool's complete audit trail without re-fetching the whole detail object. Cursor-paginated (default 50, max 200), ordered by createdAt desc, filterable by kind CSV (CHECK_OUT, CHECK_IN, AUDIT, REPAIR_LOGGED, ...) and a since ISO date. Each event carries the structured description field — STOCK_ADJUSTMENT events use a 'stock_adjusted:' prefix, PM service completions use 'pm_serviced:'. Integrations mirroring tool history into accounting or asset systems should hit this instead of paginating through the JSON detail endpoint. 7 contract tests cover the scope gate, cross-tenant 404, kind-CSV filtering (drops unknown kinds), since-date parsing, cursor passthrough, and limit clamping.
Learn more → - new
PM service-completion: 'Mark serviced today' button + API endpoint
Closes the PM-overdue loop end-to-end. Iter 63 surfaced PM-overdue tools; iter 86 makes resolving the overdue trivial — POST /api/v1/tools/{id}/mark-serviced (tools:write) updates lastServicedAt and creates a structured AUDIT ToolEvent. Optional `at` body field for back-dating historical service records. UI button appears on /tools/{id} when pmIntervalDays > 0; mechanics finishing service tap it and the PM-overdue chip + dashboard widget clear on the next render. 6 new tests cover the 404 / no-interval-gate / back-dating / structured-prefix paths.
Learn more → - new
Tool depreciation: straight-line book value via ?includeBookValue=true
GET /api/v1/tools/{id}?includeBookValue=true tacks a bookValue sub-object onto the response with the straight-line depreciated estimate: purchaseCost * max(0, 1 - elapsedYears / usefulLifeYears). Defaults are 5 years for non-consumables, 1 year for consumables; pass ?usefulLifeYears=10 (or 0.25-50) to override. Future-dated purchases clamp to full purchaseCost; past-useful-life clamps to 0. Tools missing purchaseDate or purchaseCost return null bookValue so accounting consumers know to backfill instead of seeing a fake $0. New fleetToolBookValue(orgId) helper returns an org-wide rollup (totalPurchaseCost, totalBookValue, count by category, count of tools missing data) for the eventual /tools dashboard widget. 13 new tests cover the math + the rollup grouping + the RETIRED-exclusion.
Learn more → - new
Stock-adjustment endpoint + tool.low_stock webhook
POST /api/v1/tools/{id}/adjust-stock records a signed delta against a consumable tool's stockLevel — positive = restock, negative = usage. Records an AUDIT ToolEvent with a structured stock_adjusted: delta=N new_level=M prefix so audit consumers can parse the change. When the adjustment causes a crossing from above-threshold to at-or-below-threshold, a NEW tool.low_stock webhook fires automatically (wire it to reorder automation or Slack); the event includes previousStockLevel, newStockLevel, and the effective threshold. 12 new tests cover validation (delta=0, NaN, Infinity), the consumable-only 409 gate, zero clamping, AUDIT-event creation, and the conditional webhook fire on threshold cross vs. no-crossing paths.
Learn more → - new
CSV export for the tools inventory: GET /api/v1/tools?format=csv
Hand the spreadsheet to finance without the JSON detour. GET /api/v1/tools accepts ?format=csv and returns a text/csv attachment with a 22-column stable layout — name, category, status, stock + threshold, assignment, checkout state, purchase data, PM cadence, scan token. Same filter surface as the JSON path: status, category, lowStock, pmOverdue all narrow the export. RFC-4180 quoting handles tool names with commas / quotes / newlines safely. 9 new tests pin the header, the boolean rendering, the null handling, and the filter pass-through to isLowStock / isPmOverdue.
Learn more → - new
Kit bulk check-out / check-in — one action moves the whole socket set
POST /api/v1/tools/{id}/checkout and /checkin now accept includeChildren: true. When set, the action fans out across the kit Tool itself plus every child whose parentKitId points at it — a mechanic grabbing a socket set creates 30 CHECK_OUT events (one per socket + the case) with one HTTP call. Each child still produces its own ToolEvent + tool.checked_out / tool.checked_in webhook + auto work order on BROKEN. Per-child failures (already-out, RETIRED, MISSING) land in skipped[] without aborting the rest. 6 new tests cover the kit-fan-out, the cross-tenant 404 path, and the no-children case where only the kit itself moves.
Learn more → - fixednew
Tool webhooks wired up: tool.failure now actually fires + new tool.checked_out / tool.checked_in
tool.failure was declared in the public AsyncAPI spec since the v1 launch but no lib path ever called enqueueWebhookEvent — subscribers got nothing. Wired the emission inside reportToolIssue + BROKEN check-ins so the event fires for both paths. Also added two new event types: tool.checked_out (fires from checkoutTool, payload includes targetUser + linkedAsset) and tool.checked_in (fires from checkinTool, includes the observed condition + newStatus + auto-spawned workOrderId on BROKEN). Same HMAC-SHA256 signing + 5-minute replay window + ABANDONED-after-12h retry behavior as the existing webhooks. All three are best-effort enqueues — a webhook backend hiccup never blocks the check-out itself.
Learn more → - new
Tool checkout utilization: GET /api/v1/tools/{id}/utilization
New endpoint that pairs CHECK_OUT events with the next CHECK_IN, sums durations (clamped to the window), and returns total checkout-ms + utilization percentage + top-N users by time. Window defaults to 30 days (1-365 valid); topN defaults to 3 (max 10, set to 0 to omit per-user breakdown). Open checkouts close at 'now' and the response flags openAtWindowEnd=true. Tools:read scope; 14 new tests cover edge cases (clamping, open checkouts, force-override consecutive checkouts, top-N sorting).
Learn more → - new
Tool PM-overdue surface: filter + API + dashboard helper
Tools with a pmIntervalDays cadence now surface as 'PM overdue' once the elapsed days since lastServicedAt (or createdAt if never serviced) crosses the interval. A new chip on /tools alongside All / Mine / Needs repair / Low stock; the row picks up an amber 'PM overdue' marker. GET /api/v1/tools accepts ?pmOverdue=true; composes with ?lowStock=true. pmOverdueTools(orgId, limit) dashboard helper returns the worst offenders by days-past-due. 16 new tests for isPmOverdue + pmOverdueTools + API filter; 878 total pass.
Learn more → - new
Low-stock alerts for consumables (filter + API + dashboard helper)
Added a per-tool minStockLevel field (null = use org fallback of 5) and a lowStock=true filter on GET /api/v1/tools that returns consumables where stockLevel <= COALESCE(minStockLevel, 5). The /tools page picked up a 'Low stock' chip alongside All / Mine / Needs repair; rows now render the stock level inline with amber emphasis when low. A lowStockTools(orgId, limit) helper sorts asc by stockLevel for dashboard widgets. 17 new tests for isLowStock + lowStockTools + the API filter; 862 total pass.
Learn more → - new
Tool check-out / check-in / report-issue endpoints in the public API
Three new tool-action endpoints — POST /api/v1/tools/{id}/checkout (idempotent per actor, force-overrides existing checkouts), POST /api/v1/tools/{id}/checkin (records observed condition; BROKEN auto-spawns a HIGH-priority WorkOrder and returns the new workOrderId so you can deep-link the shop into it), POST /api/v1/tools/{id}/report (failure or replacement-request flow, optional markMissing). All three are tools:write and follow the same partial-success / cross-tenant-404 envelope as the rest of /api/v1.
Learn more → - new
Integration landing pages × 6: Zapier, Slack, QBO, Samsara, Geotab, John Deere, Komatsu
Concrete how-to pages under /integrations covering the most-asked vendor connections. Each page follows a three-pattern shape (minimal / middle / deep) with copy-paste code. /blog/integration-pages-pattern is the synthesis post documenting the template so the next page is a 90-minute fill-in.
Learn more → - new
Migration guide at /docs/api/migration
Three end-to-end scripts for moving onto DirtFleet — Fleetio → DirtFleet (handles their ZIP-of-CSVs export), generic CSV → DirtFleet, Whip Around → DirtFleet. Uses the bulk-import endpoints + per-record idempotency keys derived from source-row ids so re-runs are safe.
Learn more → - new
API recipes + SDK codegen guide + AsyncAPI spec
/docs/api/recipes ships five complete end-to-end integration scripts (CSV import, weekly export, Postgres flag mirror, Slack alerts, daily email). /docs/api/sdk has copy-paste codegen commands for TS / Go / Python / Ruby. /asyncapi.yaml is the AsyncAPI 2.6 spec for the webhook event surface — generate typed event handlers the same way you generate typed REST clients.
Learn more → - new
Blog tag filter pages
/blog/tag/{tag} filters posts by tag with prerendered pages for every distinct tag. Tag chips on /blog and /blog/[slug] are clickable. Related-posts block appears at the bottom of each post (3 most-recent posts sharing a tag).
Learn more → - new
Public REST API: full CRUD-lite across assets, flags, hours, work orders, tools, projects, yards, repairs, webhooks
Iterations 21-50 built out the public /api/v1/* surface to ~33 routes. Full CRUD-lite on every primary resource (list / detail / create / update / batch where it matters). HMAC-signed webhooks for eight event types. Cross-tenant 404, never 403. /docs/api + /docs/api/recipes + /docs/api/sdk; OpenAPI 3.1 at /openapi.yaml; AsyncAPI 2.6 at /asyncapi.yaml; Postman collection at /postman_collection.json.
Learn more → - new
Bulk-import endpoints for the five heaviest resources
POST /api/v1/{assets,hours,projects,tools,yards}/batch — partial-success semantics, parallel results[] indexed to input order, per-entry error reporting. The 'switching from Fleetio / Samsara' migration is one round-trip per chunk.
Learn more → - newimproved
Per-key rate-limit overrides
ApiKey.rateLimitPerMinute opt-in column. Enterprise contracts negotiate per-key caps without a code change; the global default (60 rpm) still applies when null. Surfaces on /api/v1/me + every X-RateLimit-Limit response header for the affected key.
Learn more → - newsecurity
CORS + idempotency + signed webhooks for /api/v1/*
Bearer auth on every /api/v1 route with no cookie surface → Access-Control-Allow-Origin: * is safe; browser-direct integrations work. Idempotency-Key header on every write endpoint that creates rows; per-entry clientMutationId on batch endpoints. Webhook deliveries signed with HMAC-SHA256 over `${timestamp}.${rawBody}` with 5-minute replay window.
Learn more → - new
Zapier + Slack integration landing pages
/integrations/zapier ships six concrete prebuilt zap templates (red flag → Slack, WO completed → QuickBooks, hours → Sheets, urgent WO → SMS, tool failure → Slack, asset created → CMMS). /integrations/slack ships three Slack-native patterns from simplest (10-min Incoming Webhook) to richest (dedicated Slack App with /flag-resolve slash command).
Learn more → - newsecurity
Trust hub: /trust, /security, /privacy/posture, /sla, security.txt
Procurement teams asked for one landing that links every trust artifact. /trust does that. /security goes deep on the seven pillars; /privacy/posture is plain-English consent + rights; /sla covers three commitment tiers; /.well-known/security.txt follows RFC 9116.
Learn more → - new
Public roadmap (Now / Next / Later)
Three buckets at /roadmap covering 14 named items. When something ships, it leaves the roadmap and lands here on the changelog.
Learn more → - new
Customer-facing pages: /customers, /partners, /press, /careers, /about, /contact
Six pages that procurement, marketing, and recruiters need on the public site. /customers covers the day-0-to-day-30 onboarding; /partners has the three referral programs; /press has the boilerplate + assets; /careers is honest about hiring; /about + /contact close the small loops.
Learn more → - new
Industry deep-dives × 5 + the integrations directory
Construction, ag, equipment-rental, mining, logging — each now has a /industries/<vertical>/deep-dive page with the six-role daily loop, vertical-specific support, and honest-scope sections. /integrations/directory shows live vs scaffolded vs roadmap for every named integration.
Learn more → - new
Four competitor comparison pages
Honest side-by-sides at /compare/vs-fleetio, /compare/vs-samsara, /compare/vs-geotab, /compare/vs-motive, /compare/vs-whip-around. Pricing references are 2026 public ranges; we tell readers where each competitor wins.
- new
Blog: 12 founding posts
Engineering and ops writing from the team building the product. Tool tracking design, hour-based PM, anomaly detection, work-order playbook, cost-per-hour, offline-first design, no-lock-in promise, shop-spend rollup, integration-first design, AI scope + guardrails, the 25-asset fleet, accountant handoff.
Learn more → - new
Resources: PM template, OSHA 300, Davis-Bacon, QR labels
Four /resources pages with copy-pasteable content. No email gate. The PM template renders the OEM seeds (Caterpillar, John Deere, Komatsu, Cummins) as a table.
Learn more → - new
Public REST API + webhooks: /api/v1 + signed outbound events
API keys (dfk_…) with 11 named scopes, /api/v1/assets shipped with cursor pagination, signed webhooks with HMAC-SHA256 + exponential-backoff retry, dispatcher cron. Full reference at /docs/api.
Learn more → - improved
Job queue (Postgres-backed), Redis rate-limiter, Sentry shim
Async job runner using the existing webhook-dispatch cron pattern. Redis-backed rate limiter for multi-container scale (in-memory fallback). Sentry observability shim — opt-in via SENTRY_DSN.
- newsecurity
Customer impersonation + audit log UI
DirtFleet staff can view a customer org (red banner, mutations blocked). Tenant-side audit log at /settings/audit for org admins.
- improved
Spanish (es-MX) i18n + locale switcher
Driver + mechanic + tool flows have Spanish. Switch from the account menu — preference saved to a cookie.
- new
OSHA Form 300 + certified-payroll exports
Two new export endpoints: /api/export/osha300 (recordable incidents) and /api/export/certified-payroll (Davis-Bacon weekly worker × asset rollup per project).
- new
Real-time activity SSE + Resend bounce webhook + status page
/api/feed/stream pushes unified activity events (hours, flags, WOs, repairs, checklists, tool events, incidents). /api/webhooks/resend suppresses bounced addresses. /status now has live probes + a public 90-day incident timeline.
Learn more → - new
Audit + incident + cert + consent + document vault models
Schema mega-migration adds tenant audit log (AuditLog), OSHA incident reporting (Incident), operator certifications (11 kinds), GDPR/CCPA consent ledger (ConsentRecord), and asset document vault (AssetDocument).
- new
Tool tracking module + universal QR/NFC scan
Hand tools, power tools, kits, and consumables now live alongside the fleet. Scan an equipment tag to log hours; scan a tool tag to file damage / replacement. Failures auto-spawn a work order.
Learn more → - new
Real-time activity rail
The dashboard now streams live activity over SSE — hours logged, flags raised, work orders updated, tool failures, all in one rail that updates without a refresh.
- new
Public REST API + webhook subscriptions
API keys (dfk_…) with named scopes, /api/v1/assets as the first public surface, signed outbound webhooks with HMAC-SHA256 + retry backoff. Configure both at /settings.
- new
Audit log, incidents, certifications, consent
Org-level audit trail wired through mutating routes; OSHA Form 300-aligned incident module with CSV export; operator certifications (CDL, MSHA, NCCCO, OSHA 10/30); GDPR/CCPA consent ledger.
- new
Spanish (es-MX) UI strings
Driver, mechanic, and tool flows now have Spanish translations. Switch from the account menu — preference saved to a cookie.
- new
Prevailing-wage / certified-payroll export
Federal (Davis-Bacon) and state-funded jobs need weekly worker-hours certifications. New CSV export rolls up HoursLog by worker × week × asset for any project.
- new
Status page
Public /status page with live probes for web, database, webhooks, email, and photo storage.
- new
Work orders + project allocation
Quick-log stays for ad-hoc fixes; new WorkOrder model tracks assigned shop work end-to-end. Hours and repair costs roll up to projects (Davis-Bacon-friendly P&L).
Learn more → - new
Pre-trip checklists
Drivers tap PASS / FAIL / NA before logging hours. FAILs raise a yellow flag automatically. Default templates ship for on-road, off-road, and trailer.
Learn more → - new
Demo sandbox + trial-email lifecycle
/demo browses a seeded fleet without signup. Trial emails fire on day 1, 3, 7, 25, and 32 to coach onboarding and conversion.
Learn more → - improved
Per-asset Stripe metering
Org admins can switch from flat-org billing to per-asset metering. Quantity syncs to Stripe whenever an asset is added or marked as an attachment.
- improved
S3 / R2 photo storage
Photo storage now supports object storage backends (`PHOTO_STORAGE_BACKEND=s3` or `=r2`). Postgres BYTEA stays the dev default — no migration required for small fleets.
- new
Per-asset financials + DTC AI + anomaly detection
Asset purchase cost, depreciation, and TCO rollup; Gemini-backed DTC narrative endpoint; hours-delta z-score + cost-spike anomalies plug into the flag system.
- new
OEM service-catalog seeds
Bootstrap a new asset's PM list from Caterpillar, John Deere, Komatsu, Cummins, and generic-trailer templates instead of starting blank.
- security
Backup / DR runbook
Documented RPO/RTO commitments, quarterly DR drill checklist, and recovery procedures for accidental delete + region failure + corrupted blobs.
Learn more →