Conversation
…ft keyword CSVs produce complete, CSV-shaped correction objects for every supported scheme.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #134 +/- ##
==========================================
- Coverage 99.73% 99.64% -0.09%
==========================================
Files 234 236 +2
Lines 6391 6512 +121
Branches 1907 1909 +2
==========================================
+ Hits 6374 6489 +115
- Misses 16 21 +5
- Partials 1 2 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| } | ||
| }, | ||
| { | ||
| "scheme": "instruments", |
There was a problem hiding this comment.
isn't this one missing longname?
There was a problem hiding this comment.
LongName is read from the CSV, but it is not part of the hierarchy-based oldKeywordObject; long names are handled separately as oldLongName and newLongName. This is a deletion, so DIF10 only needs the hierarchy and ShortName to identify and remove the instrument; replacement corrections provide newLongName separately when <Long_Name> must be updated.
| idnnode: ['ShortName'], | ||
| dataformat: ['ShortName'], | ||
| granuledataformat: ['ShortName'], | ||
| discipline: ['DisciplineName', 'Subdiscipline'], |
There was a problem hiding this comment.
This doesn't have a csv pairing but, also I don't think its actually used in CMR at all anyways
There was a problem hiding this comment.
It does have a CSV definition: Discipline_Name,Subdiscipline,UUID, which normalizes to these object keys. You’re right that CMR does not currently consume discipline corrections; this entry only ensures the publisher would construct a correctly shaped event if that scheme is processed.
| verticalresolutionrange: ['VerticalResolutionRange'], | ||
| horizontalresolutionrange: ['HorizontalResolutionRange'], | ||
| productlevelid: ['ProductLevelId'], | ||
| measurementname: ['ContextMedium', 'Object', 'Quantity'] |
There was a problem hiding this comment.
This one is only used in umm-var so I don't think it needs the csv either
There was a problem hiding this comment.
Although MeasurementName is not currently used in CMR collections, it has the CSV columns Context_Medium,Object,Quantity,UUID. This mapping ensures those CSV fields are represented correctly in generated correction objects if collection support is added later.
| * | ||
| * @type {Readonly<Record<string, string|string[]>>} | ||
| */ | ||
| export const UMMC_FIELDS = Object.freeze({ |
There was a problem hiding this comment.
This is fine for now we might wanna figure out a common interface with CMR that we can pull from because if they change this we could silently drift really easily
There was a problem hiding this comment.
I agree, a shared interface with CMR would be a good longer-term solution because it would establish one source of truth for native field names and prevent the KMS mappings from silently drifting when CMR changes its schemas.
| 'CategoryKeyword', | ||
| 'TopicKeyword', | ||
| 'TermKeyword', | ||
| 'VariableLevel1Keyword/Value', |
There was a problem hiding this comment.
I also saw just a regular VariableLevel1Keyword in there without the /value
There was a problem hiding this comment.
ECHO10 schema requires it to contain a element. Therefore, we should not support a bare VariableLevel1Keyword; the /Value path is intentional.
| * | ||
| * @type {Readonly<Record<string, string|string[]>>} | ||
| */ | ||
| export const ISO19115_FIELDS = Object.freeze({ |
There was a problem hiding this comment.
Is this the same ones for ISO MENDS and for SMAP?
There was a problem hiding this comment.
Yes. ISO MENDS and ISO SMAP use the same ISO 19115 field names, so they share ISO19115_FIELDS and the same scheme editors. SMAP’s only relevant structural difference is its outer DS_Series/seriesMetadata/MI_Metadata wrapper, which Iso19115MetadataPathEditor adds to the XPath automatically.
| .toLowerCase() | ||
| .replace(/[^a-z0-9]/g, '') | ||
|
|
||
| const AUXILIARY_CSV_HEADERS = new Set(['uuid', 'longname', 'datacenterurl']) |
There was a problem hiding this comment.
Should this maybe just be in the consts
There was a problem hiding this comment.
Good suggestion. I moved these into constants.js and clarified that they are normalized CSV column names excluded from keyword hierarchy paths.
Overview
What is the feature?
Correct publisher keyword-event mapping so published and draft keyword CSVs produce complete, CSV-shaped correction objects for every supported scheme.
This work began with the short-name scheme defect described in KMS-705. The shared CSV comparison treated every column before
UUIDas a hierarchy position. For schemes with auxiliary columns such asLong_NameorData_Center_URL, the last auxiliary value could be emitted asShortNamewhile the actualShort_Namewas discarded. This potentially affected platforms, instruments, projects, providers, IDN nodes, data formats, and granule data formats.Since this was IP sprint, my goal was to test the complete workflow from published CSVs through generated native metadata rather than limiting validation to the initial publisher fix. This uncovered a broader contract issue: correction objects sometimes relied on positional assumptions or native metadata field names instead of the actual production CSV columns. The scope therefore expanded to formalize that contract and protect the full workflow with end-to-end regression tests.
For example, a GOSAT short-name update previously produced an unchanged event because
Long_Namewas incorrectly treated asShortName:{ "Category": "Platforms", "Class": "Space-based Platforms", "Type": "Earth Observation Satellites", "ShortName": "Greenhouse Gases Observing Satellite" }The corrected event follows the platform CSV headers and preserves both values independently:
{ "Basis": "Space-based Platforms", "Category": "Earth Observation Satellites", "SubCategory": "", "ShortName": "GOSAT", "LongName": "Greenhouse Gases Observing Satellite" }The draft object is identical except that
ShortNameis correctly set toGOSAT - Test1.The same positional behavior could lose intermediate hierarchy values. An Amazonia platform update was recorded with a new path similar to
Space-based Platforms > > Amazonia-1-Chris-Test, droppingEarth Observation Satellites. Reading the namedCategorycolumn now preserves that value, while also retaining the intentionally blankSub_Categoryslot.What is the Solution?
UUIDcolumn as an indexed hierarchy value.Basis,Sub_Category,Short_Name,Long_Name, andData_Center_URL.LongNameandDataCenterURLin correction objects without treating them as hierarchy levels.published.csvanddraft.csvfixtures for every supported keyword scheme.The end-to-end tests now verify two independent boundaries:
afterrecord for both updates and deletions.The generated corrections are deliberately not passed directly into the native transformation assertion. Keeping the two stages independent prevents a broken publisher from defining its own expected native result. It also gives us a repeatable pattern for future mapping defects: add the production-shaped CSV case, the expected correction object, and the affected native metadata field, then the test locks the reported behavior from publication through transformation.
What areas of the application does this impact?
Testing
npm test -- --run serverless/src/shared/__tests__/applyNativeMetadataCorrectionMappings.test.js.npm test -- --runand confirm the full suite passes. The current result is 226 test files and 2,296 tests passing.npm run lintand confirm ESLint passes.beforenative metadata fixture for comparison, then compare it with the correspondingafterfixture underserverless/src/shared/__mocks__/native_metadata_correction_mappings/end_to_end._CHANGEDvalues appear only in intended mapped fields,_SHOULD_DELETEvalues are absent from deletion results, and unrelated metadata is unchanged.generated/short-name-events.jsonand confirm short-name schemes preserve the true short name plus auxiliary long-name or provider URL values.Attachments
The production-shaped CSV inputs, expected publisher events, correction objects, and complete before/after native records are included under
serverless/src/shared/__mocks__/native_metadata_correction_mappings/end_to_end.Checklist