Skip to content

Worker Tier — Not Built

The worker tier is the part of Demostatics that is supposed to gather and process the world’s data. Every other component on this site describes itself in terms of it. It does not exist in code, in any of the five repositories.

Planned. The founding specification describes the worker tier as the platform’s computational backbone: a worker-based task processing system, built as a high-performance C/C++ application, designed to run across multiple platforms and hardware environments while coordinating machine learning models and large language models functioning as distributed worker nodes.

Hardware is assumed to be heterogeneous — CPU-only systems through to GPU-accelerated machines — and each worker node is meant to be configured to operate efficiently in its own environment, whether a local machine, a dedicated server or cloud infrastructure.

In that design, the ML models and LLMs are themselves specialized workers. Their job is to turn unstructured global inputs into structured, meta-descriptive data, standardized across five analytical dimensions — time, capital, workforce, material-energy, information — and stored for immediate or future use.

Planned. Everything in this section comes from the founding specification. None of it has an implementation to check it against.

The spec calls for a detailed and flexible configuration layer with four parts:

PartWhat it is meant to doStatus
Hardware-aware setupAutomatic detection of CPU, RAM and GPU capabilitiesPlanned
Platform-specific optimizationTailored configuration per operating system and architecturePlanned
Manual overridePrecise control over performance parameters, task allocation and execution behaviourPlanned
Task-specific configurationDifferent processing rules per workload type — ML inference, data parsing, news aggregationPlanned

At runtime, workers are meant to communicate with a central server, receive tasks, execute them, and transmit processed results back over a structured communication protocol. Two modes are specified:

  • Sequential execution for controlled environments.
  • Parallel batch execution for high-throughput scenarios.

Performance is to be bounded by configurable limits:

  • Maximum parallel jobs
  • Memory usage limits
  • Execution timeouts

A built-in module is meant to monitor execution continuously, capturing processing time, memory consumption and system load, for transparency, debugging and ongoing optimization.

The detector layer is specified as the interface between server and workers. It listens for incoming tasks, filters them by worker or group identity, and routes them into the appropriate execution queues.

+--------------------+
| central server | demostatics-web today; not connected to anything
+---------+----------+
| tasks
v
+--------------------+
| detector layer | listen -> filter by worker/group id -> route
+---------+----------+
|
+--------+--------+--------------+
v v v
+---------+ +---------+ +---------+
| worker | | worker | | worker | CPU-only and GPU nodes
| (CPU) | | (GPU) | | (LLM) |
+---------+ +---------+ +---------+
| structured results
v
+--------------------+
| standardized store | time / capital / workforce / material-energy / information
+--------------------+
Implemented in code: none of the above.

Three things, none of which is a worker.

A placeholder repository. One commit (Initial commit), one branch (main), one tracked file. That file is README.md and it is two lines:

# worker-pc
This repo is about worker-pc backends that will operate the system.

There is no source directory, no build file, no language declared, no CI, no license.

Worker-shaped leftovers in demostatics-web

Section titled “Worker-shaped leftovers in demostatics-web”

The display tier carries several artifacts that were clearly created for the worker and are connected to nothing.

ArtifactWhat it isStatus
reports tableCreated by demostatics-web/database/migrations/2024_12_31_234146_create_reports_table.php. Read by ReportsController and Api\V1\ReportController. Rows are written only by database/seeders/ReportSeeder.php and directly by tests (tests/Feature/ReportsExportTest.php, tests/Feature/PortabilityTest.php, tests/Feature/Api/WorkerDataApiTest.php)Table Shipped, producer Not built
database_items tableCreated by demostatics-web/database/migrations/2026_07_17_130000_create_database_items_table.php. Read by DatabaseController and Api\V1\DatabaseItemController. Rows are written only by database/seeders/DatabaseItemSeeder.php and a test factoryTable Shipped, producer Not built
tasks tableCreated by demostatics-web/database/migrations/2025_07_09_130123_create_tasks_table.php. A full job-scheduling schema. Nothing reads or writes itNot built (orphaned)
App\Models\TaskAn empty Eloquent model — a class body containing one comment. Referenced from nowhere in the repositoryNot built (orphaned)
TokenAbility::INGESTThe string ingest:write in demostatics-web/app/Support/TokenAbility.php. Deliberately excluded from forInteractiveDevice(). Granted to no token; required by no routePlanned (reserved vocabulary)
App\Enums\JobConfig, JobDefinition, JobPriority, JobStatusFour job-scheduling enums/classes in demostatics-web/app/Enums/. Referenced only by each otherNot built (orphaned, and partly broken)

The tasks table columns are a complete job-scheduling vocabulary that nothing populates:

task_id (unique) job_type parameters (json)
priority estimated_time_sec dependencies (json)
deadline creation_timestamp retry_count
max_retries status result_location
isOpen

TokenAbility states the intent plainly in its own docblock: the ability exists so that “a route added later can say ->middleware('abilities:ingest:write') and have it actually mean something”. A test in tests/Feature/Api/TokenHardeningTest.php asserts that device tokens do not carry it. That is the whole of the worker’s presence in the security model.

There is no ingest endpoint. demostatics-web/routes/api.php exposes GET /reports and GET /database-items for reading and nothing for writing. No worker client exists in any repository, and no worker credential has ever been minted.

Where the rest of the platform assumes it exists

Section titled “Where the rest of the platform assumes it exists”

Every one of these was read and quoted directly from the file named.

FileThe assumption it makes
demostatics-web/README.md”A separate worker backend (running on other machines) gathers and processes data — news, reports, geographic and meta-descriptive listings — and stores it. This repository does not gather or process anything.
demostatics-web/database/migrations/2024_12_31_234146_create_reports_table.php”This is the display-tier contract for a worker-produced report row.”
demostatics-web/database/migrations/2026_07_17_130000_create_database_items_table.php”The Database page shows the latest worker-produced values, filterable by the same geo + category dimensions as Reports.”
demostatics-web/database/seeders/ReportSeeder.php”Real reports come from the worker tier in production.”
demostatics-web/database/seeders/DatabaseItemSeeder.php”Real values come from the worker tier in production.”
demostatics-web/docs/api-v1.mdHeads the Reports and Database section with “The worker-produced tiers”, and justifies withholding ingest:write so a stolen device token “cannot reach a worker-only endpoint”
demostatics-web/app/Support/TokenAbility.phpReserves ingest:write for “a worker credential” and notes that without abilities “a leaked phone token is also an ingest credential”
demostatics-mobile_application/README.md”The data those tiers display is produced elsewhere, by a separate worker backend that runs on other machines. Neither this app nor the web app gathers or processes anything.”
demostatics-mobile_application/docs/roadmap.md §4aAssigns rollups and threshold evaluation to it: “Continuous processing over the dataset belongs to the worker tier … So Laravel stores alert rules, serves them, and notifies; the worker decides when one fires.”
demostatics-mobile_application/docs/roadmap.md §5Scopes the whole programme against “a worker backend that does not exist in any of these repos”

Two independent repositories therefore document a hard dependency on a component that has never been written. See the system map for how that gap sits in the platform as a whole.

This is not a missing optimization. It is the reason the product has no numbers.

There is no numeric time series anywhere. database_items.value is a VARCHAR holding a display string. The seeded rows are literal values like 48,210 MW, 62.4 USD/MWh and 38 AQI. The column is never cast, parsed or aggregated. Each row carries a single measured_at and there is no history table, so a value has a timestamp but no series.

Everything downstream follows from that:

Blocked capabilityWhy
ChartsNothing to plot — no series, and no numeric type
Statistics over real dataAggregation over a display string is not defined
Thresholds and conditional alerts”Crossed a line” needs a comparable number and a prior value
The desktop analytics stackds-analytics, ds-graph, ds-charts and ds-compute all consume f64. There is no Demostatics source that produces one
RollupsAssigned to the worker by the roadmap; no other tier is supposed to compute them

The desktop client’s analytics are real and they work — against its own examples/mock-stream-server. They have never been pointed at Demostatics data because Demostatics has no numeric data to point them at. See the web component for what the display tier can and cannot supply.

What the investment-company decision adds to its job

Section titled “What the investment-company decision adds to its job”

Not built. The decision to operate as an investment company does not make the worker exist, and nothing in this section changes that. What it changes is the specification the worker will have to be written against.

Under the four-line positioning on Business Model, the same pipeline feeds paying subscribers, the firm’s advisory calls, its managed portfolios and its own trading book. That makes the worker more than a data producer. It becomes the producer of records the firm may have to defend — to a client, to an auditor or to a regulator — years after the figure was published and acted on.

Three obligations follow, and all three land on the worker rather than on the display tier:

  • Emit source attribution and method version with every observation. A number stops being a number and becomes a number plus where it came from, how it was derived, and which version of that method produced it. A revised model produces a different value, so the record has to say which model produced which value.
  • Write revisions append-only. A correction is a new row, not an overwrite. The value someone acted on has to stay readable after it has been superseded, along with when the supersession happened.
  • Never silently restate a published value. Once a figure has been published or acted on, changing it is an event with its own record — not an in-place edit that leaves no trace the earlier value ever existed.

The full record-keeping requirement — including measured-at and ingested-at as two separate facts, and point-in-time reconstruction of what was known at a given moment — is set out on Business Model and Regulatory Posture. Neither page is legal advice, and the obligations that actually apply depend on a jurisdiction that is undecided; counsel has to settle them.

These come from demostatics-mobile_application/docs/roadmap.md and are unresolved.

Who owns it, and will it emit numerics? Roadmap §2 lists this as an open decision: the worker backend “is in none of the three repos and is the hard dependency for charts, thresholds and conditional timers”. Until someone owns it and commits to emitting numbers rather than display strings, no downstream phase is safe to start.

Which tier computes what? Roadmap §4a draws the line: request-scoped arithmetic — a quote, a tally, a paginated answer — belongs in Laravel; continuous processing over the dataset — rollups, evaluating threshold rules across every series on a schedule — belongs in the worker. Putting the second in Laravel “would quietly turn the display tier into a compute tier”.

Which dataset identifier namespace? Roadmap Phase 1 requires the contracts to agree on “one dataset identifier namespace shared with the worker”, covering both the web/mobile API and the desktop’s separate contract. Two clients currently use different identifier schemes, and the worker would have to satisfy both.

Roadmap Phase 2 — Numeric time series, from source is the phase that creates the worker’s write path. As documented it adds metrics, metric_observations, metric_rollups and a units table, plus an ingest endpoint behind the scoped ingest:write ability with an Idempotency-Key. Rollups are to be computed by the worker and written in, not derived by Laravel on a schedule.

Phase 2 must now also include provenance, which the roadmap previously left to a later phase: source and method with a method version on every observation, measured-at and ingested-at as separate columns, and an append-only revision history that supports point-in-time reconstruction. The ingest contract has to carry those fields, which means the worker has to produce them from its first write rather than acquire them later.

database_items becomes a projection over the new tables so that GET /api/v1/database-items stays byte-identical for existing clients. The roadmap is explicit that the seven seeded rows are to be converted by hand rather than recovered with a regex parser, because the worker already holds the values as f64.

Phase 2 is estimated at 4-6 weeks and is described as “the technical unlock for the whole product”. Nothing has started. See the roadmap for how it sits against the other phases.