Context
The openstreetmap-logical-history-component (LoCha) is a Vue 3 component library for visualizing OSM logical history diffs. The goal is to use it as a third-party dependency in clearance-frontend, replacing its custom diff/map/changeset components.
To do this, the GET /projects/{slug}/changes_logs endpoint needs to return data shaped as a GeoJSON FeatureCollection matching LoCha's ApiResponse type, instead of the current LoCha[] array format.
Important: The current LoCha ApiResponse format was designed for a single LoCha group at a time (the OSM logical history API returns one group per request). The Clearance API returns many LoCha groups in a single response. This should already work with the target format since metadata.links is a Record<number, ApiLink[]> — multiple group IDs can coexist. The features[] array can contain features from different groups, each referencing its group via properties.links.
Current response shape
LoCha[] → Log[] → Subject (base/change)
Each Log contains inline base/change Subject objects, diffs, and changesets.
Target response shape (ApiResponse)
{
"type": "FeatureCollection",
"features": [ /* IFeature[] - flattened GeoJSON Features */ ],
"metadata": {
"links": { /* Record<number, ApiLink[]> - group relationships + diffs */ },
"changesets": [ /* Changeset[] */ ]
}
}
See full type definitions: https://github.com/teritorio/openstreetmap-logical-history-component/tree/develop/src/types
Required changes
1. Structural transformation
| Current |
Target |
LoCha[] (array of groups) |
GeoJSON FeatureCollection with metadata |
Log.base / Log.change (inline Subject) |
Flattened into features[] as GeoJSON Features |
Subject.geom (property on Subject) |
Lifted to feature.geometry (GeoJSON standard) |
Diffs (diff_tags, diff_attribs) on each Log |
Moved to metadata.links[groupId] as ApiLink[] |
| Changesets per-Log |
Collected into a single metadata.changesets[] array |
2. Fields to add (no current equivalent)
| Field |
Type |
Notes |
properties.geom_distance |
number | null |
Distance between before/after geometries |
properties.username |
string |
Derivable from changeset user |
ApiLink.conflation_reason |
Reason |
Object with geom (score, reason), tags (score, reason), conflate |
3. Field format changes
| Field |
Current |
Target |
objtype |
'n' | 'w' | 'r' |
'node' | 'way' | 'relation' |
4. Fields unchanged (already compatible)
Actions / Action types — structurally identical between both projects
Changeset — field-for-field identical
diff_tags, diff_attribs — same shape
action ('accept' | 'reject') — same
5. Current fields with no LoCha equivalent
These fields are not consumed by the LoCha component. They can either be dropped from this endpoint or kept alongside for clearance-frontend to use separately:
Log.matches (Match[]) — validator/quality-rule info
Subject.changeset_id
Alternative approach
Instead of modifying the existing endpoint, a new endpoint (e.g. /projects/{slug}/changes_logs/locha) could return the LoCha-compatible format, keeping the current endpoint intact for backward compatibility.
Context
The openstreetmap-logical-history-component (LoCha) is a Vue 3 component library for visualizing OSM logical history diffs. The goal is to use it as a third-party dependency in clearance-frontend, replacing its custom diff/map/changeset components.
To do this, the
GET /projects/{slug}/changes_logsendpoint needs to return data shaped as a GeoJSON FeatureCollection matching LoCha'sApiResponsetype, instead of the currentLoCha[]array format.Important: The current LoCha
ApiResponseformat was designed for a single LoCha group at a time (the OSM logical history API returns one group per request). The Clearance API returns many LoCha groups in a single response. This should already work with the target format sincemetadata.linksis aRecord<number, ApiLink[]>— multiple group IDs can coexist. Thefeatures[]array can contain features from different groups, each referencing its group viaproperties.links.Current response shape
Each
Logcontains inlinebase/changeSubject objects, diffs, and changesets.Target response shape (
ApiResponse){ "type": "FeatureCollection", "features": [ /* IFeature[] - flattened GeoJSON Features */ ], "metadata": { "links": { /* Record<number, ApiLink[]> - group relationships + diffs */ }, "changesets": [ /* Changeset[] */ ] } }See full type definitions: https://github.com/teritorio/openstreetmap-logical-history-component/tree/develop/src/types
Required changes
1. Structural transformation
LoCha[](array of groups)FeatureCollectionwithmetadataLog.base/Log.change(inline Subject)features[]as GeoJSON FeaturesSubject.geom(property on Subject)feature.geometry(GeoJSON standard)diff_tags,diff_attribs) on each Logmetadata.links[groupId]asApiLink[]metadata.changesets[]array2. Fields to add (no current equivalent)
properties.geom_distancenumber | nullproperties.usernamestringApiLink.conflation_reasonReasongeom(score, reason),tags(score, reason),conflate3. Field format changes
objtype'n' | 'w' | 'r''node' | 'way' | 'relation'4. Fields unchanged (already compatible)
Actions/Actiontypes — structurally identical between both projectsChangeset— field-for-field identicaldiff_tags,diff_attribs— same shapeaction('accept' | 'reject') — same5. Current fields with no LoCha equivalent
These fields are not consumed by the LoCha component. They can either be dropped from this endpoint or kept alongside for clearance-frontend to use separately:
Log.matches(Match[]) — validator/quality-rule infoSubject.changeset_idAlternative approach
Instead of modifying the existing endpoint, a new endpoint (e.g.
/projects/{slug}/changes_logs/locha) could return the LoCha-compatible format, keeping the current endpoint intact for backward compatibility.