Skip to content

Gap Register

This is the complete register of what is missing. A five-lens sweep of the five repositories — security; legal and privacy; operations; commercial; engineering and AI governance — looked for absences rather than bugs, and found 86 of them.

Nothing here is on fire, because nothing is deployed and nobody is paying. Every entry is a statement about the cost of fixing something later versus now. The sequenced answer to “so what do I do” lives on What To Do Next; this page is the reference it points at.

The sweep deliberately excluded anything already documented elsewhere on this site. The thirteen code contradictions and the decision register on Open Questions, the two-contract conflict on The Two Contracts, the launch blockers on Deployment Readiness, and the phase plan on the Roadmap are all still live and are not repeated here. This register is additive — if a thing appears on both, the entry here is a different problem with a similar name, and says so.

Four columns carry through every table.

ColumnMeaning
GapThe absence. Named as what is missing, not as what to build.
Why it mattersOne sentence. The detail is in the finding this row compresses.
EffortRough order of magnitude for one engineer: hours, days, weeks, months.
WhenThe latest point at which closing it is still cheap.

The When vocabulary is exactly four values, in this order of urgency:

  • Now — the cost of the fix rises from today, either because a schema is about to be designed around its absence or because an asset is not being accumulated.
  • First customer — before anyone pays. Most of the register sits here.
  • Licence — before a licence application is made or a regulator asks.
  • Scale — before there are many users, many machines, or real volume.

Within each severity group, rows are sorted by When first and then by effort ascending, so the cheap urgent things are at the top of every table.

Counts are read directly out of the findings file, not estimated.

SeverityCountNowFirst customerLicenceScale
Existential52210
High42132810
Medium3522544
Low40202
Total86175766

By lens, and by effort:

LensExistentialHighMediumLowTotal
Security088218
Operations and reliability198018
Legal, privacy and data rights088117
Commercial and financial viability2123017
Engineering, data science, AI governance258116
EffortCount
Hours27
Days37
Weeks21
Months1

Two things fall out of that distribution. Twenty-seven of the 86 are hours of work — mostly configuration, a file, or a guard clause — which means roughly a third of the register could be cleared in a fortnight of deliberate, boring work. And 17 are marked Now, of which the majority are not engineering at all: they are documents, decisions and a small amount of paperwork.

These five are separated out because each one, left alone, invalidates work done on top of it. They are not the five most urgent — three of them are cheap and none of them is a crisis today. They are the five where a wrong answer discovered late means throwing away months.

1. No detection that a produced number is wrong

Section titled “1. No detection that a produced number is wrong”

Operations and reliability · weeks · before licence

Missing. There is no reconciliation against a second source, no outlier or bounds check, no revision-versus-previous-value comparison, and no concept of a data-quality alarm anywhere in the platform. App\Models\DatabaseItem and App\Models\Report contain $fillable and casts and nothing else — no validation, no observer, no mutator. There is no ingest endpoint to validate at, because routes/api.php has no write path into either table. No test asserts anything about the plausibility of a value.

Why it matters here. The founder decision of 2026-08-01 puts the firm on both sides of these numbers: it sells them by subscription, advises on them, manages client capital against them and trades its own book on them. Meanwhile database_items.value is a string column holding a display string — '48,210 MW', '0.734' — so a wrong value is not even type-detectable. A decimal-place error, a unit swap or a hallucinated classification lands in the table looking exactly like a correct value, sorts to the top of the Database page by measured_at, and is served to subscribers and to the trading desk identically.

The failure. A worker misparses a feed and writes '4,821,000 MW' where it meant '48,210 MW'. The page renders it, the API serves it, a position is taken on it, and the first person who notices is a counterparty or a client. Because rows are overwritten in place with no history — updateOrCreate in the seeders is the only writer pattern that exists anywhere — you cannot afterwards show anyone what the number was at the moment the decision was made, or that it was ever different. A loss plus an unreconstructable file is the combination that costs a firm its permission to operate.

The fix is not one thing; it is the smallest useful subset of a validation layer, chosen before the ingest endpoint is designed. See Model Risk and Ground Truth.

2. No cost-of-goods model, and the founding source list has two readings ~100x apart

Section titled “2. No cost-of-goods model, and the founding source list has two readings ~100x apart”

Commercial and financial viability · days · now

Missing. No document, spreadsheet, config file, code comment or README in any of the five repositories attaches a cost to anything. No COGS model, no infrastructure sizing, no per-source price, no inference budget, no cloud estimate, no split between fixed and variable cost. A grep across all five repositories for currency amounts returns zero monetary figures — every $ is a PHP variable or Rust syntax. Business Model discusses four revenue lines and never mentions cost once.

Why it matters here. The nine declared sources on Data Pipeline can be read two ways, and the two readings are different companies.

Scenario A — the cheap path. Free and open sources at modest scale: one always-on ingest VM, managed Postgres or Timescale, object storage for a raw archive, free Sentinel-2 and Landsat imagery with some processing, and LLM classification of roughly 20k documents a day on a small model. Order of magnitude: $500–$5,000 a month, and the largest single swing factor is model choice.

Scenario B — the founding document taken literally. Google Maps plus Yandex plus Baidu plus social media plus commercial satellite plus continuous LLM at worldwide scale. Sampling a thousand traffic corridors every fifteen minutes is millions of routing calls a month; a social firehose is a five-figure monthly line on its own; commercial satellite tasking is five to six figures a year minimum; LLM over half a million documents a day is another five-figure line at frontier pricing. Order of magnitude: $50,000–$250,000 a month, which is $600k–$3M a year before a single salary.

The gap between those two readings is the entire strategic question and nobody has noticed it exists. Scenario A is fundable by one person. Scenario B needs institutional venture capital before it produces a single row of data.

The failure. The founder builds toward the founding document’s source list, signs up for a mapping platform, connects a news firehose, and discovers the cost structure by receiving a bill in month one — at which point the pipeline is architected around sources that have to be ripped out. The quieter failure is worse: an investor or a customer asks “what does it cost you to produce a report” in a first meeting, and there is no answer, which reads as the founder not understanding his own product.

3. No funding plan, no runway, no use of funds — and licensing costs money, not only time

Section titled “3. No funding plan, no runway, no use of funds — and licensing costs money, not only time”

Commercial and financial viability · weeks · now

Missing. No financial model, no cap table, no funding ask, no use-of-funds breakdown, no monthly burn, no runway calculation, no milestone-to-raise mapping. The pitch deck has ten slides — Title, Problem, Solution, Product, Technology, Market Opportunity, Business Model, Interactive Community, Vision, Why Demostatics — and contains no ask, no traction, no team slide, no financials, and no numbers of any kind. There is nothing to raise against.

Why it matters here. Every document on this site treats licensing as a clock: “months to years, and no amount of engineering shortens it”. That is true and it is half the picture. Authorisation regimes generally also carry minimum capital requirements — the firm has to hold and maintain regulatory equity, and the amount typically differs between advisory and discretionary management. What those amounts are, and whether they apply, is a question for counsel in a jurisdiction that has not been chosen. The structural point does not need counsel: line 3 cannot be started with zero capital regardless of how long you wait, and no document anywhere acknowledges that licensing has a price as well as a duration.

Stacked on that: a compliance officer is a salary, not a checkbox; discretionary management implies a custodian, an administrator, an auditor and professional indemnity cover; and proprietary trading is not a revenue line at all — it consumes capital, and no document says where the firm’s own trading book comes from. Meanwhile the platform itself needs money for whichever COGS scenario is chosen, plus 9–18 months of a founder’s time.

The failure. The founder reaches the end of the engineering plan having burned personal runway, then discovers that starting the licensing path requires capital he does not have and cannot raise on a deck with no numbers in it — while the four-line decision has already committed him to a structure that needs all of it. See Cost and Funding and Regulatory Posture.

Engineering, data science and AI governance · weeks · before first customer

Missing. There is no concept anywhere in the platform of validating a model, measuring its accuracy, detecting drift, backtesting a signal, attaching a confidence interval, or requiring a human to approve a machine-produced figure before it is published. No policy document, no code, no schema column, no test. A case-insensitive grep across every .md, .php, .rs, .ts and .tsx file in all five repositories for the vocabulary of model governance returns eleven hits, every one of which is either “drift” meaning API-contract drift or unrelated tooling boilerplate. A search for ML artifacts — *.py, *.ipynb, requirements*.txt, *.onnx, *.gguf, *.safetensors — returns nothing at all across all five repositories.

Why it matters here. The entire premise is that ML models and LLMs turn messy world inputs into numbers; Worker Tier says the models “are themselves specialized workers”. The 2026-08-01 decision means the firm will advise clients, manage their capital and trade its own book on those numbers. That makes model output the firm’s core risk exposure, and it is currently unmanaged in the strict sense — not badly managed, not managed at all. From inside the system, a model that is wrong is indistinguishable from a model that is right.

The failure. A processing worker reads a figure reported in thousands as units and publishes a country’s industrial output an order of magnitude low. It lands in database_items, renders on the Database page, is sold to subscribers, feeds an advisory call and sizes a position on the firm’s own book. Nothing anywhere compares it to anything. It is discovered when a client challenges it — at which point the firm cannot say how the number was produced, cannot reproduce it, and cannot show that any other number it has ever published was checked either.

This is the cheapest existential item to start on, because at zero rows the framework can be written as a page of rules that the schema is then designed to satisfy. See Model Risk and Ground Truth.

5. No ground truth: nothing can say whether a Demostatics number is correct

Section titled “5. No ground truth: nothing can say whether a Demostatics number is correct”

Engineering, data science and AI governance · weeks · before first customer

Missing. There is no reconciliation against any authoritative external source, no reference dataset, no accuracy metric, and no mechanism by which the firm could ever answer “is our figure for X right?” — for any X. No repository contains code that reads an external reference and compares it to a stored value. There is no fixtures directory, no golden dataset, and no expected column, table or file anywhere in demostatics-web/database/.

Why it matters here. This is a different thing from finding 4. Model validation is a process; ground truth is the measuring instrument that process needs, and you cannot build the process without it. Several of the declared sources — ISO datasets, FX rates, national statistics — publish figures that are themselves the authoritative answer for quantities Demostatics intends to derive. Nothing plans to compare the two. Without that comparison there is no accuracy number to put in a subscription pitch, no way to detect a source that has silently changed format, and no basis on which to price the product against a competitor’s.

The failure. A prospective institutional subscriber asks the only question that matters — “how accurate is your data, and how do you know?” — and there is no answer, no historical error series, and no way to produce one retroactively, because no observation was ever recorded alongside a reference value. The sales conversation ends there.

The only values that exist in the product today are seven hand-written strings in DatabaseItemSeeder.php and twelve hand-written reports in ReportSeeder.php. That is also the opportunity: choosing the reference series now costs a page of writing, and choosing it after a million rows exist costs a backfill that cannot be done.

Forty-two findings, grouped by lens. Thirteen of these are marked Now; they are at the top of their tables.

Detail and the recommended order of work are on Security and Privacy.

GapWhy it mattersEffortWhen
Live known-vulnerable dependencies, and nothing scans PHP or JavaScriptcomposer audit reports 28 advisories across 11 packages, and two of the highs sit in the mail and routing path the next deployment step switches onhoursNow
No threat model in any repositoryEvery other security decision — information barriers, publication ordering, what gets logged — depends on naming the adversary, and this firm’s adversary set is unusualdaysNow
Changing a password does not revoke anythingupdatePassword never deletes tokens, so the compromised session a user is trying to kill survives for up to 30 days; the reset path a few methods away gets this right and has a test for ithoursFirst customer
The demo seeder creates a live admin with the password passwordNo seeder carries an environment guard, and the credentials are published in the README, in docs/api-v1.md and on this sitehoursFirst customer
No security event loggingThe whole Laravel app makes one Log:: call; a valid credential reading everything produces zero errors and zero alerts, and afterwards nothing can say which account, from where, or whendaysFirst customer
The paid data surfaces have no rate limit and no usage accountingbootstrap/app.php never calls throttleApi(), so /reports and /database-items are unthrottled and unmetered, and no future usage tier has anything to price againstdaysFirst customer
No second factor on any account, including the administratorAdmin authority is protected by a password alone, and the first enterprise security questionnaire asks this question directlyweeksFirst customer
Insider risk is operationally unaddressedOne person can edit database_items.value — which has no provenance, no revision history and no source column — and also builds the side of the business that trades on itweeksFirst customer

Investment licensing itself is on Regulatory Posture and is not repeated here.

GapWhy it mattersEffortWhen
Third-party code entered the tree with no assignmentThe mobile app’s entire first commit came from an outside contributor via an AI app builder, with no CLA and no assignment on file; this is fixable today and stops being fixable when people are unreachabledaysNow
Ingested-source rights have nowhere to live in the schemaProvenance answers “where did this come from”; it does not answer “may we sell it”, and the four business lines may hold different rights on the same rowweeksNow
Account deletion leaves rows behind, and the two paths differThe web path never deletes tokens, personal_access_tokens and model_has_roles carry no foreign key, and the test suite certifies only the half that worksdaysFirst customer
Poll votes are identified opinion records on political topicsThe unique index on (user_id, poll_id) makes the ballot identified by construction, stored forever, with no consent record and no retention limitdaysFirst customer
No subscriber contract, liability limit or accuracy statementNothing states what the firm commits to or caps, exports carry no notice and no customer fingerprint, and the Windows installer already asserts subscription terms that have never been writtenweeksFirst customer
No privacy notice, lawful-basis position or data inventoryThe system holds more personal data than an inventory-free team would guess, and the inventory gets harder to assemble every monthweeksFirst customer
Erasure and the moderation record destroy each otherDeletion cascades posts, votes and the ban record together, so the only erasure available simultaneously over-deletes and under-deletes, and nobody has chosen which obligation winsweeksFirst customer
No founder-side paper: shareholding, vesting, IP assignmentAn entity does not own the code until it is assigned, and assignments signed after a dispute or a second founder are much harder than assignments signed nowdaysLicence
GapWhy it mattersEffortWhen
app:delete-unverified-users is an unguarded mass deleteUnder the documented default MAIL_MAILER=log no user can ever verify, so its selection criterion matches the entire user table; no dry run, no confirmation, no log, no backup behind ithoursNow
Bus factor of one, with no credential inventory158 of 163 commits are by one person, every .env is correctly gitignored, and nothing records where the domain, the store accounts or the future APP_KEY livehoursNow
No backup of anything, anywhereThe live database is one untracked SQLite file; user accounts, forum history, votes and the curated paid rows are derivable from nothinghoursFirst customer
Nothing polls /api/v1/health, and there is no alert destinationThe health endpoint’s only consumer is a customer-facing footer in the mobile app; the diagnosis exists and the detection does nothoursFirst customer
No error tracking in any of the three shipped codebasesServer exceptions land in a file on the box; a mobile render throw is a white screen with no report and no error boundaryhoursFirst customer
The external world dataset has no recorded versionEvery stored country_id is a bare integer pointing into a community dataset whose ids have been renumbered across releases, with no foreign key and no version pinhoursFirst customer
No trusted-proxy configurationThe moment TLS is terminated in front of the app, every auth throttle keys on the proxy address, so one bucket of five attempts per minute is shared by the whole internethoursFirst customer
A silently stopped feed is indistinguishable from a quiet worldNothing computes freshness; measured_at is read only to sort and to display, so a dead source renders as an unchanged indicatordaysFirst customer
No restore has ever been attempted and no recovery procedure existsThe restore has non-obvious steps — the external geo store, APP_KEY, the scheduler cron, the queue worker — that will be discovered under pressuredaysFirst customer
GapWhy it mattersEffortWhen
No price, no break-even seat count, no cash cost on the 9–18 month planThe break-even arithmetic is trivial once COGS exists and it changes what gets built; the roadmap sequences engineering as if time were the only scarce resourcedaysNow
No minimum viable data setNothing names which sources are required to ship something sellable versus which are aspirational, which is why “what is the smallest thing you could sell in six months” has no answerdaysNow
The history clock has not startedPoint-in-time history is the one asset that can only be accumulated in real time; a dumb archiver could run this week and would be worth more in two years than any downstream engineering done meanwhiledaysNow
No competitor is named anywhereThe incumbents’ prices anchor the positioning, and a one-person firm cannot win on breadth — the entry has to be narrow, and that is a decision nobody has madedaysNow
Three of the four business lines cannot produce revenue for yearsAdvisory and discretionary management wait on a licence, proprietary trading consumes capital rather than producing recurring revenue, so line 1 funds everything alonedaysNow
Almost all cost is fixed, and the only allowance table meters the cheap thingsA high-fixed, near-zero-marginal structure reduces the business to “how many seats amortize the pipeline”; the mock server’s dev limits meter egress and the customer’s own CPU, and give Enterprise unlimited AIdaysFirst customer
The satellite claim is unsourced and uncostedFlight, maritime and road data do not come from imagery, and the one genuine use case is served by free public programmes — so the expensive part of “satellite” is not required by anything the product describesdaysFirst customer
Mapping provider terms likely prohibit what the model does with the dataStoring refined data and reselling it collides with the redistribution and derived-dataset restrictions common to those platforms; this needs checking before a line of ingestion code is writtendaysFirst customer
The single asset is bulk-extractable by any verified accountNo throttle, no quota, no usage record, no watermark and no redistribution term; the control has to exist before the data does, because retrofitting it onto existing customers is a renegotiationdaysFirst customer
Nothing can collect money, and the named payment rail may be unavailableNo billing code, no plans or invoices tables, no tax handling, no currency decision — and the roadmap’s Phase 3 assumption needs checking against the entity’s country before the entitlement system is designed around itweeksFirst customer
There is no top of funnel, and no way to measure oneThe homepage redirects to an editorial list, the contact page refuses personal email addresses, and no analytics of any kind exist anywhereweeksFirst customer
The four named buyer segments cannot procedurally buyEvery one of them requires terms, a DPA, security documentation and often a formal audit posture before a purchase order can be raised; first revenue realistically comes from somewhere elsemonthsFirst customer

Engineering, data science and AI governance

Section titled “Engineering, data science and AI governance”
GapWhy it mattersEffortWhen
No output contract can express uncertaintyEvery delivered number is a bare scalar, so a figure corroborated by three sources is indistinguishable from one an LLM inferred from a single article — and adding the field later leaves every historical row permanently nulldaysNow
No worker design specThe decisions that must precede writing the worker — orchestration, idempotency, delivery semantics, retry, backpressure, binding output to a model version — exist nowhere, while an orphaned tasks table sits in the wrong repository encoding a guess at themweeksNow
The composite risk score has no documented methodologyIt is a mean coefficient of variation weighted by how many series each category happens to contain, saturating at a constant with no stated justification, presented as a risk modelweeksFirst customer
The risk score depends on the viewer’s tier and requested update rateA Pro subscriber computes a structurally different number from an Individual subscriber for the same world, and nothing in the UI or the contract says soweeksFirst customer
Observations have no time axisEvery displayed statistic is computed over arrival index, and the correlation table aligns two front-dropping windows by prefix, so two clients can see materially different r for the same pairweeksFirst customer

Thirty-five findings. None of them will stop a launch on its own; most are cheap, and several are hours of work sitting in front of a much larger cost.

GapWhy it mattersEffortWhen
No vulnerability disclosure pathNo SECURITY.md, no security contact, no security.txt — and public installers are the artefact an unsolicited researcher pokes at firsthoursFirst customer
Report export writes untrusted strings into spreadsheetscsv() and xlsx() neutralise nothing while doc() in the same class escapes everything; the tables will be worker-populated from scraped texthoursFirst customer
The desktop client takes the password as a command-line flagVisible in ps, captured in shell history and collected by exactly the endpoint tooling the intended customer runs; there is no stdin, env or prompt alternativehoursFirst customer
The release pipeline publishes a dev build authenticated by a hardcoded passwordThe release job never enables the remote feature, so everything good in the client’s security design is compiled out and the shipped credential is demohoursFirst customer
Release supply chain: mutable action refs with write access, no provenanceFive third-party actions pinned to tags, workflow-level write permission on every build job, and a checksum file generated by the pipeline it is meant to attesthoursFirst customer
CORS is open to every origin and no security response headers are setAny hostile page can drive the unthrottled public API from a visitor’s browser, and there is no CSP behind the forum’s user-submitted bodieshoursFirst customer
No incident containment capabilityNo way to freeze one account, stop new signups, or expire tokens issued before a date; the only blunt instrument takes the whole business offlinedaysFirst customer
The desktop assistant is an unpoliced exfiltration channelLive indicator values and base64 screenshots of the workspace POST to whatever URL a command-line flag names, with no allowlist, scheme check or audit recorddaysScale
GapWhy it mattersEffortWhen
No licence file anywhere, and the server’s manifest declares itself MITcomposer.json still carries the Laravel skeleton’s name and MIT licence on the only implemented server, which says the opposite of the desktop repository’s proprietary declarationhoursNow
The one third-party dataset already shipping has no recorded licence or attributionThe geo cascade is redistributed through a public unauthenticated API with no terms recorded anywhere and no notice carried to the point of deliveryhoursNow
Ban status and presence are published to unauthenticated callersUserResource emits is_banned, roles and is_online on every public forum listing, so an adverse statement about identified people is world-readablehoursFirst customer
Mail written to an unrotated log makes reset tokens permanentWhile MAIL_MAILER=log is set, the log is a mail archive containing account-granting tokens, with no rotation, no retention and no erasure pathhoursFirst customer
No breach-notification path, and the contact page repels reportersThe notification clock starts on awareness, and awareness usually arrives from a private individual writing from a personal address — which the page states will not be accepteddaysFirst customer
Forum rule 17 points at an empty report endpointThe route exists and its controller body is a TODO comment; there is no reports table, no moderator queue, and no channel at all for a non-userdaysFirst customer
No insurance of any kind is named anywhereSelling a number people act on, and later advising on money, are the exposures these policies exist for; cover is also a common condition of authorisation and of institutional contractsweeksFirst customer
Running the firm’s compute on customers’ machines has no disclosure textOnce the coordinator lands, the firm is sending work to hardware it does not own, and nothing states what runs, whose work it is, or how to withdrawdaysScale
GapWhy it mattersEffortWhen
The production log sink is an unrotated file at debug levelLOG_STACK=single with LOG_LEVEL=debug on a small VPS where the database, sessions, cache and queue share one disk; a daily channel exists and is simply not selectedhoursFirst customer
Desktop crash reports are written and never sentThe panic hook writes a file to the user’s machine that nobody will ever open, so the crash rate of every shipped version is permanently unknowndaysFirst customer
No staging environmentChanges go from one laptop to production, and the cross-driver behaviours the code carefully handles are never executed against Postgres or MySQL by anything, everdaysFirst customer
A 5000-row export runs synchronously in the request with no rate limitThe paid feature builds an entire spreadsheet in memory inside the worker that is also serving everyone else, and nothing throttles itdaysFirst customer
Mobile has no kill switch, no OTA channel, and a build-time-baked API originOnce a build is in a store, the only lever is a new submission; the server also does not know what version any client isdaysFirst customer
No on-call, no incident procedure, no availability commitmentAn always-connected streaming subscription is a product whose customers notice downtime in minutes, and nobody has decided what happens at 3amdaysFirst customer
No cost ceiling or circuit breaker on any paid external dependencyAn LLM proxy has unbounded cost per request by design — images, long context, tool loops — exposed to a client the firm does not control, with no cap and no alarmdaysFirst customer
Every authenticated request rewrites one shared cache key, and nothing has been load testedA read-modify-write of a single global entry on every request, on a single-writer SQLite file; it is both a serialization point and a lost-update racehoursScale
GapWhy it mattersEffortWhen
Single-provider dependency with no substitution layerEvery layer rests on one named provider, two of them with a documented history of unilateral repricing, and there is no seam behind which a second source could be dropped indaysFirst customer
The pricing model bills customers for compute their own hardware performsCharging for statistical work executed on the customer’s laptop is hard to hold in a renewal, and the meter that would count it is client-side and does not exist as a cratedaysFirst customer
Turkish non-dilutive funding and technology-zone status are mentioned nowhereGrant programmes and R&D tax regimes exist for close to this exact profile, and eligibility depends on an entity structure being decided right now for regulatory reasonsweeksLicence

Engineering, data science and AI governance

Section titled “Engineering, data science and AI governance”
GapWhy it mattersEffortWhen
Statistics are fitted to visually-downsampled dataAbove 64 samples the fit runs over LTTB output — a perceptual algorithm that over-selects extrema — and the resulting R² is handed to the AI assistant as the authoritative summaryhoursFirst customer
Automatic model selection by in-sample R², then extrapolatedR² never decreases with complexity, so the cubic usually wins on noisy data, and the chosen curve is extrapolated with confident prose about growth to infinitydaysFirst customer
Polynomial fitting has no conditioning guardRaw index powers to Σx⁶ against an absolute pivot threshold produce coefficients that have silently lost most of their significant digits rather than returning NonedaysFirst customer
No test exercises a real customer path across two componentsEvery test is intra-repository and each side is tested against its author’s belief about the other, which is exactly the class of failure the two-contract problem will produceweeksFirst customer
No output artifact can be reconstructed after the factExports carry no as-of time, no build version, no filters and no sample counts, and the in-memory history behind them is discarded on exitdaysLicence
No change control over methodologyThe constants that move every displayed number are ordinary constants in ordinary files, with no method version, no changelog and no gate — while the site commits to adapting the platform by community votedaysLicence
AI assistant output is unrecorded and unattributedNothing persists an exchange, the model identity, the grounding context or the tools called, and the local path already emits trading suggestionsweeksLicence
Contributed compute has no result-verification designOnce the coordinator exists, output the firm sells and trades on will have been computed on machines it does not control, by users with a financial interest in its positionsweeksScale
GapLensWhy it mattersEffortWhen
No secret scanning anywhereSecurityNothing would have caught the live Gemini key that sat in demostatics-web history for 20 revisions, and the next roadmap steps create SMTP, payment and eventually broker credentials. .gitignore also covers .env.backup but not .env.bakhoursNow
Bundled fonts carry notice obligations and no third-party licence file shipsLegalcargo-deny verifies a licence is allowed; it does not generate the notice file, and nothing else does eitherhoursFirst customer
The desktop caches proprietary data to disk in plaintext and never clears itSecurityThe token is deliberately protected and the thing the token protects is not; nothing wipes the snapshot on logout, expiry or downgradehoursScale
Documentation is the system of record and nothing verifies itEngineeringThis site makes several hundred checkable claims and has no build check, no link checker and no CI; the first broken claim discounts everything else on ithoursScale

The sweep also looked for things done well, and found roughly fifty. This section exists for two reasons: it tells you what not to touch while working through the register, and it is the evidence that the register is a survey rather than a pile of complaints. The items below were re-verified against the repositories while writing this page.

  • Every .env is gitignored, in the web, desktop and docs repositories, and .env.example ships empty placeholders rather than real values.

  • Every lockfile is committed: composer.lock and package-lock.json in the web repo, Cargo.lock in the desktop workspace, package-lock.json in mobile, pnpm-lock.yaml here.

  • Sanctum token expiry is set explicitly. config/sanctum.php line 58 reads env('SANCTUM_EXPIRATION', 60 * 24 * 30) — a 30-day default in place of Laravel’s shipped null, which means tokens that never expire. That is a deliberate hardening of a framework default and it is the kind of thing that is normally missed.

  • Scoped token abilities exist. App\Support\TokenAbility declares a real vocabulary — data:read, forum:write, account:write, moderate, ingest:write — with ingest:write deliberately withheld from every interactive token, and a docblock explaining why the vocabulary had to be declared before a second kind of token exists. (Two known gaps in how it is applied are already logged as contradictions 4 and 5 on Open Questions.)

  • Forgot-password does not enumerate accounts. The API returns the same body whether or not the address exists, with a comment in AuthController explaining that otherwise “anyone could walk a list of addresses through”.

  • There is no file-upload surface at all. A grep across app/, resources/views/ and routes/ for hasFile, UploadedFile, Storage::putFile and enctype returns nothing. An entire vulnerability class is absent by construction.

  • No unescaped Blade output. {!! !!} appears nowhere in resources/views/, across a forum that renders user-submitted bodies up to 40,000 characters.

  • Raw SQL is disciplined. Seven whereRaw/orderByRaw call sites, every user-supplied value bound as a parameter, every column name supplied by controller code and never from the request. The LOWER(col) LIKE ? pattern carries a comment explaining it exists because a bare LIKE is case-sensitive on PostgreSQL.

  • WebPKI validation plus optional SHA-256 certificate pinning on the desktop QUIC transport (crates/ds-transport/src/quic.rs), with the insecure bypass an explicit, documented opt-in rather than a default.

  • cargo-deny runs in CI on the Rust workspace with an allow-listed licence set and a single ignored advisory that carries a written justification and a revisit condition.

  • Welford’s online algorithm for running mean and variance rather than the naive sum-of-squares (crates/ds-analytics/src/streaming.rs), with a test asserting it matches the batch result.
  • Bessel-corrected sample variance — divides by n-1 — in both the batch and streaming paths, documented as such in each.
  • Two-pass Pearson correlation (crates/ds-analytics/src/correlation.rs) rather than the numerically unstable single-pass form.
  • Degenerate inputs return Option::None, not NaN. A caller cannot accidentally render a garbage number, because there is no garbage number to render.

Those four are the reason the analytics findings in this register are about methodology rather than arithmetic. The arithmetic is careful.

  • Every one of the 22 migrations has a real down(). Not one is a stub.
  • 211 Laravel tests, 922 assertions, green in 2.2 seconds — re-run while writing this page. A suite that fast gets run, which is most of the value of having one.
  • The hand-written Feature serde implementation in crates/ds-core/src/identity.rs exists because of a real bug, and its test asserts that an unknown feature name still parses rather than failing the whole payload — forward compatibility deliberately chosen.
  • Every repo-relative path cited on this docs site exists. All 57 distinct paths quoted in backticks across src/content/docs/ were checked against disk. The claims are accurate today; the LOW finding above is about keeping them that way, not about fixing them.