Task: Bring ores.geo to the clean standard

Table of Contents

This page documents a task in the Clean ores.geo to the component clean standard story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

ores.geo passes the Component Clean Standard for a component of kind All.

ores.geo is a hand-written, model-less C++ library, so the model, protocol, wiring and shell sections do not apply. The audit found stale documentation, hygiene defects and a test suite that could not fail, and the rewritten test found a real defect in the component's SQL. The item table records that outcome item by item. V06 records the programme gap.

2. Status

Field Value
State DONE
Parent story Clean ores.geo to the component clean standard
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-09-26

3. Acceptance

  • Every checklist item that applies to a component of kind All passes, or is recorded with the reason it does not apply.
  • Every item that cannot pass is recorded as an exception with its reason.
  • Every generator defect found is fixed at its source, with a regression test.
  • No consumer is left broken. The whole tree builds with the component.

The original acceptance asked that ores.geo join COMPONENTS_UNDER_TEST. That cannot be met and is superseded, because ores.geo is not a codegen component. V06 records the reason.

4. Plan

The survey below was recorded on 2026-09-25 by an agent that did not write the component. Every finding was re-verified on this branch before the work, and one defect the survey missed was found by the rewritten test.

Item Result Evidence
B01 pass Baseline before any edit. No catalogue row, so the drift gate cannot name the component: check_component_drift.py --component geo --dry-run answers Unknown component: 'geo', and --all passes for iam. regenerate_cmake_component_files.py --component ores.geo --check reported 2 stale files, src/component_files.cmake and tests/component_files.cmake. check_model_drift.py reports no drift, with the 2 known exceptions in compute and reporting.
B02 pass 0 entity, junction, operation, message, field-group and module models. projects/ores.geo/modeling/ holds component_overview.org (#+type: ores.codegen.component), ores.geo.puml and ores.geo.png.
B03 pass 5 production C++ files classified: 4 headers (export.hpp, ores.geo.hpp, service/geolocation_service.hpp, service/ores.geo.service.hpp) and one 74-line source, service/geolocation_service.cpp. tests/ holds geolocation_service_tests.cpp and main.cpp. All are hand-written infrastructure; none matches a codegen archetype's output and none is dead. The two umbrella headers are included by nobody and are kept as the component and facet namespace documentation, which the codegen convention generates for every component.
B04 not applicable The component serves and sends no NATS subject and has no protocol header.
B05 pass Two live captures under doc/agile/product_backlog/next/ name the component. geo_location_tests_fail_for_some_ip_addresses.org records the test defect this task confirms and closes. fix_component_doc_drift.org names it in an affected-components snapshot that is stale for geo, since validate_docs.sh now passes for every component. No in-flight branch touches the component.
M01 not applicable No org entity model.
M02 not applicable No entity model, so no variability profile to bind.
M03 not applicable No model states a property.
M04 not applicable No model feature to place in a namespace.
M05 not applicable No entity, so no table to describe.
M06 not applicable The component exchanges no wire type and has no hand-written protocol header.
M07 not applicable No junction.
M08 not applicable No org-model custom-type binding.
M09 not applicable No model, so no legacy fragment to find in one.
M10 fail, fixed The overview claimed MaxMind GeoLite2-City, city plus coordinates, three geoip_* tables and ores.iam as the consumer. The service reads ores_geo_ip2country_tbl through ores_geo_ip2country_lookup_fn, is country-only, and ores.http is the consumer. The overview is rewritten with the six sections and id-linked See also, and validate_docs.sh passes for the component.
P01 not applicable No entity and no protocol.
P02 not applicable No subject is owned.
P03 not applicable No registrar and no declared message.
P04 not applicable No operation model.
P05 not applicable No protocol change reaches a consumer.
P06 not applicable No event cache.
G01 not applicable No model, so nothing regenerates.
G02 pass No hand-written file the generation supersedes remains.
G03 fail, fixed The two component_files.cmake files carried no generated marker; both now carry the marker and their template name.
G04 not applicable No generated code.
G05 pass The one defect found is an SQL defect, not a template defect, and V02 records its fix and its regression test. The diagram is hand-massaged, so a capture run rewrites the section above the sentinel; the warning below the sentinel records that, and the second pass is in the Notes.
G06 fail, fixed regenerate_cmake_component_files.py --component ores.geo --check now reports All component_files.cmake up to date.
W01 not applicable No registrar family, so no composition point.
W02 not applicable No handler checks a permission.
W03 not applicable No populate script names the component.
W04 not applicable The component owns no SQL script of its own; its schema lives under projects/ores.sql/create/geo/.
S01 not applicable No entity or junction, so no shell command unit.
S02 not applicable No command, so no recipe and no destructive flag.
H01 pass, findings fixed The Component Architecture Audit ran and its record is this task. Shape: a simple component matching the signed-off folder catalogue (CMakeLists.txt, include/, src/, tests/, modeling/). No leftover artefact, no platform-specific code, no commented-out code, names snake_case and matching their types. Two findings were fixed: the overview's stale claims, and the same claims on the Foundation layer page. Complexity measure: lizard gives 75 NLOC over 4 functions, average cyclomatic complexity 2.8, and no warnings.
H02 fail, fixed A dead database_not_available enum value and an unused <optional> include are removed; the enum stays out of the regenerated diagram. The two umbrella headers are kept and their MaxMind text is corrected. The unused PUBLIC ores.geo.lib link in projects/ores.iam/core/src/CMakeLists.txt is removed, since ores.iam uses no geo symbol and ores.http.core links the library itself.
H03 fail, fixed The service header named geolocation_import.sql, and the file on disk is ip2country_import.sql. That script cannot run either: it omits the NOT NULL tenant_id. The comment now states the real data path, that the dq ip2country publish path is the only writer.
V01 pass compass build over the whole tree reached 100% with exit code 0.
V02 fail, fixed The five original cases could not fail: three wrapped their assertion in if (!result.has_value()), and two asserted on a plain struct. They are replaced with four cases that call the public API and assert literal values: a seeded range returns its country code, an unparseable string returns invalid_address, a private address returns address_not_found, and an uncovered address returns address_not_found. The seeded case then found a production defect: ores_geo_inet_to_bigint_fn read the inet_send header bytes rather than the address, so it returned 35651588 for every IPv4 address and no lookup could ever match a range. It is fixed at source in projects/ores.sql/create/geo/geo_ip2country_create.sql, which now uses the inet difference operator. The suite passes 8 assertions in 4 test cases, and the seeded case fails again if the conversion regresses. The ores.codegen suite passes at 550, and the ores.compass suite at 230 passed and 1 skipped, both re-measured after the final rebase.
V03 not applicable No entity and no service. The database was still recreated from scratch to deploy the SQL fix, and it succeeded, which is the fix's own from-scratch proof.
V04 not applicable No generated shell command.
V05 pass Every gate run and green: component drift (iam), model drift (2 known exceptions), protocol twin coverage, handler permissions, populate references, shell recipe inventory, regenerate_cmake_component_files.py --component ores.geo, validate_docs.sh (all 40 components pass), compass lint, and the six checks of .github/workflows/doc-lint.yml.
V06 not applicable No catalogue row and no models, so the component cannot join COMPONENTS_UNDER_TEST. Recorded as the programme gap the ores.connections and ores.orgmode stories already describe.

5. Notes

Survey, 2026-09-25, at trunk 5de59e3fb8, by an agent that did not write the component. Every claim was re-verified on this branch.

  • Keep the component. The retirement hypothesis fails: ores.http builds the service at application.cpp:86 and calls lookup at iam_routes.cpp:502 inside the login handler, and the result becomes session.country_code. That is the only production call site.
  • The use is inert, for two independent reasons.
    1. The geo table is empty after a recreate. compass db recreate loads the ip2country TSV into the dq staging table only. The dq publish function ores_dq_ip2country_publish_fn is the only writer of ores_geo_ip2country_tbl, and no recreate step runs it. Measured after the recreate: geo_rows=0, artefact_rows=512186. The standalone ip2country_import.sql cannot fill it either, because its insert omits the NOT NULL tenant_id, and no aggregator runs it.
    2. The IP conversion was wrong. This the survey missed, and the rewritten test found it. ores_geo_inet_to_bigint_fn computed the address from get_byte(inet_send(ip), 0..3), which on this PostgreSQL are the family, bits, is_cidr and address-length bytes. It therefore returned 35651588 for every IPv4 address, so even a populated table could not answer. The fix uses ip_address - '0.0.0.0'::inet, which returns the address as an integer for any IPv4 address.
  • Scale. 5 production C++ files in 4 headers and 1 source, with 2 files under tests/. Originally 5 test cases and 5 assertions that could not fail; now 4 cases and 8 assertions that can.
  • The data path is recorded, not wired. Wiring the publish into the recreate flow is a data-pipeline change, not a component clean-up: the natural insertion point ip2country_populate.sql is generator-owned and already drifted, the publish is a SECURITY DEFINER truncate-and-reload of about 512k rows, and a backlog capture already exists for moving ip2country onto the org dataset pipeline. The overview and the service header now state that a fresh database answers address_not_found until a publish has run.
  • The diagram runs the two passes. The capture gives the class boxes, and the hand pass adds the members and relationships they do not carry, such as the constructor, the two lookup signatures and the service-to-result and service-to-error arrows. PlantUML resolves a relationship only in the namespace block that declares its classes, so the hand-authored lines sit above the sentinel, and the warning below the sentinel says a capture run rewrites them.

Work items, and their outcome.

  1. Overview rewritten. Done, see M10.
  2. Stale ground truth fixed on the Foundation layer page. The ores.utility.hpp header that carried the same claim no longer does: the geo facet it advertised never existed, and its restored text drops it. Done.
  3. Unused ores.geo.lib link removed from ores.iam/core. Done, see H02.
  4. See also filled with id links to ores.database, ores.http.core, ores.http.server and the Foundation layer page. Done.
  5. Tests rewritten so they can fail. Done, see V02. It found the conversion defect.
  6. Data path decided: recorded, not wired. See the note above.
  7. Hygiene: the unused <optional> include removed, the dead enum value removed, the stale script name corrected. Done.
  8. Umbrella headers kept with corrected text, because the component and facet umbrella headers are the documented namespace headers. Done.

6. Test Scenarios

Manual QA scenarios (scaffolded via compass add test_scenario) that verify this task. Link new ones here as they're created; the scenario doc itself links back via its "Verifies task" field.

No scenario applies. No user reaches the component directly; the one consumer is the login route, and the change is a doc, hygiene, test and SQL fix. The build, the component suite and the gates are the evidence.

Scenario State Notes
     

7. PRs

PR Title
#2165 [geo] Massage the component diagram by hand
#2160 [geo] Bring the component to the clean standard

8. Review

# Comment summary File Decision Notes
1 The test builds its seed and clear SQL by string concatenation ores.geo/tests/geolocation_service_tests.cpp dismissed execute_raw_command takes a raw string, every input is a compile-time constant or a harness-generated UUID, and the surrounding test code uses the same pattern. There is no injection path today.
2 The ores.geo row on the Foundation layer page is not column-aligned with the rest of the table projects/modeling/system_model_foundation.org dismissed Cosmetic. Org reflows alignment on the next edit, compass lint passes, and the table's other rows are unaligned.
3 The recorded codegen suite count, 530, is stale task_clean_geo.org fixed Real. Re-measured after the final rebase: 550 passed.
4 B05 misidentifies the second capture as this task's own story task_clean_geo.org fixed Real. The two captures under doc/agile/product_backlog/next/ that name the component are geo_location_tests_fail_for_some_ip_addresses.org and fix_component_doc_drift.org.
5 The branch was not rebased onto trunk, so the verdict's base did not match the PR's feature/clean-geo fixed Real. Rebased onto trunk before landing, and the record was re-measured on the rebased tree.

9. Result

ores.geo is brought to the Component Clean Standard short of the registry entry, which the standard's own exception rule covers.

The component is a hand-written simple library, and it stays. The work is a rewritten overview and the same stale claims removed from the Foundation layer page, the generated marker on its two CMake source lists, a hygiene pass that removed a dead enum value, an unused include and the stale script name, an unused link removed from ores.iam.core, and tests that can fail.

The tests found a defect the survey missed. ores_geo_inet_to_bigint_fn converted an IP address from the inet header bytes, so it returned 35651588 for every IPv4 address and no lookup could ever match a range. It is fixed at source, and the seeded test fails again if it regresses.

Verification. The whole tree builds with compass build, exit 0. The ores.geo suite passes 8 assertions in 4 test cases, the ores.codegen suite 550, and the ores.compass suite 230 with 1 skipped. The database recreates from scratch, which is the SQL fix's own proof. Every codegen gate passes.

The one exception is V06. ores.geo does not join COMPONENTS_UNDER_TEST because it is not a codegen component.

The data path is recorded, not wired. A database built from scratch answers address_not_found until the dq ip2country publish path has run; the overview and the service header now say so.

Emacs 29.3 (Org mode 9.6.15)