@disclosureos/instruments 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/constants/index.d.ts +7 -0
- package/dist/constants/index.js +111 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/factories/index.d.ts +15 -0
- package/dist/factories/index.js +28 -0
- package/dist/factories/index.js.map +1 -0
- package/dist/formatters/index.d.ts +11 -0
- package/dist/formatters/index.js +38 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/guards/index.d.ts +6 -0
- package/dist/guards/index.js +111 -0
- package/dist/guards/index.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +228 -0
- package/dist/index.js.map +1 -0
- package/dist/labels/index.d.ts +11 -0
- package/dist/labels/index.js +38 -0
- package/dist/labels/index.js.map +1 -0
- package/dist/manifest/index.d.ts +289 -0
- package/dist/manifest/index.js +104 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/validators/index.d.ts +17 -0
- package/dist/validators/index.js +138 -0
- package/dist/validators/index.js.map +1 -0
- package/package.json +103 -0
- package/schema/sensor-manifest.schema.json +473 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/manifest/types.ts","../../src/guards/index.ts"],"names":[],"mappings":";;;;AAgBA,IAAM,kBAAA,GAAqB,sBAAA;AAEpB,IAAM,cAAA,GAAiB,CAAA,CAC3B,IAAA,CAAK,CAAC,OAAA,EAAS,iBAAA,EAAmB,iBAAA,EAAmB,SAAA,EAAW,eAAA,EAAiB,WAAW,CAAC,CAAA,CAC7F,SAAS,mDAAmD,CAAA;AAIxD,IAAM,gBAAA,GAAmB,CAAA,CAC7B,IAAA,CAAK,CAAC,cAAA,EAAgB,iBAAA,EAAmB,KAAA,EAAO,QAAA,EAAU,SAAS,CAAC,CAAA,CACpE,QAAA,CAAS,sDAAsD,CAAA;AAI3D,IAAM,kBAAA,GAAqB,EAC/B,MAAA,CAAO;AAAA,EACN,UAAA,EAAY,gBAAA;AAAA,EACZ,iBAAA,EAAmB,EAChB,MAAA,EAAO,CACP,UAAS,CACT,QAAA,EAAS,CACT,QAAA,CAAS,qEAAqE;AACnF,CAAC,EACA,IAAA,CAAK,EAAE,EAAA,EAAI,cAAA,EAAgB,CAAA,CAC3B,QAAA;AAAA,EACC;AACF,CAAA;AAIK,IAAM,oBAAA,GAAuB,EACjC,MAAA,CAAO;AAAA,EACN,YAAY,CAAA,CACT,MAAA,GACA,QAAA,EAAS,CACT,SAAS,6DAA6D,CAAA;AAAA,EACzE,iBAAiB,CAAA,CACd,MAAA,GACA,QAAA,EAAS,CACT,SAAS,kEAAkE,CAAA;AAAA,EAC9E,oBAAoB,CAAA,CACjB,OAAA,GACA,QAAA,EAAS,CACT,SAAS,oFAAoF,CAAA;AAAA,EAChG,yBAAyB,CAAA,CACtB,OAAA,GACA,QAAA,EAAS,CACT,SAAS,yFAAyF;AACvG,CAAC,EACA,IAAA,CAAK,EAAE,EAAA,EAAI,gBAAA,EAAkB,CAAA,CAC7B,QAAA;AAAA,EACC;AACF,CAAA;AAIK,IAAM,iBAAA,GAAoB,EAC9B,MAAA,CAAO;AAAA,EACN,QAAQ,CAAA,CACL,MAAA,GACA,QAAA,EAAS,CACT,SAAS,wEAAwE,CAAA;AAAA,EACpF,cAAA,EAAgB,EACb,MAAA,EAAO,CACP,UAAS,CACT,QAAA,EAAS,CACT,QAAA,CAAS,oEAAoE,CAAA;AAAA,EAChF,YAAA,EAAc,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,sCAAsC,CAAA;AAAA,EAC9F,QAAA,EAAU,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,qCAAqC;AAC3F,CAAC,EACA,IAAA,CAAK,EAAE,EAAA,EAAI,aAAA,EAAe,CAAA,CAC1B,QAAA;AAAA,EACC;AACF,CAAA;AAIK,IAAM,qBAAA,GAAwB,EAClC,IAAA,CAAK,CAAC,KAAK,GAAG,CAAC,CAAA,CACf,QAAA,CAAS,sEAAsE,CAAA;AAI3E,IAAM,4BAAA,GAA+B,EACzC,MAAA,CAAO;AAAA,EACN,GAAA,EAAK,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,gCAAgC,CAAA;AAAA,EAC/E,CAAA,EAAG,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,sCAAwC,CAAA;AAAA,EACrF,CAAA,EAAG,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,kDAAkD,CAAA;AAAA,EAC/F,IAAA,EAAM,qBAAA,CAAsB,QAAA,EAAS,CAAE,QAAA;AACzC,CAAC,EACA,IAAA,CAAK,EAAE,EAAA,EAAI,wBAAA,EAA0B,CAAA,CACrC,QAAA;AAAA,EACC;AACF,CAAA;AAIK,IAAM,iBAAA,GAAoB,EAC9B,MAAA,CAAO;AAAA,EACN,IAAA,EAAM,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,kDAAkD,CAAA;AAAA,EACnF,IAAA,EAAM,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,+DAA+D,CAAA;AAAA,EAChG,WAAA,EAAa,6BAA6B,QAAA;AAC5C,CAAC,CAAA,CACA,KAAK,EAAE,EAAA,EAAI,eAAe,CAAA,CAC1B,SAAS,sDAAsD,CAAA;AAI3D,IAAM,uBAAA,GAA0B,EACpC,IAAA,CAAK,CAAC,QAAQ,sBAAA,EAAwB,aAAA,EAAe,YAAY,CAAC,CAAA,CAClE,QAAA;AAAA,EACC;AACF,CAAA;AAIK,IAAM,uBAAA,GAA0B,EACpC,MAAA,CAAO;AAAA,EACN,MAAA,EAAQ,uBAAA;AAAA,EACR,UAAA,EAAY,EACT,OAAA,EAAQ,CACR,UAAS,CACT,QAAA,EAAS,CACT,QAAA,CAAS,oFAAoF,CAAA;AAAA,EAChG,aAAA,EAAe,EACZ,MAAA,EAAO,CACP,UAAS,CACT,QAAA,EAAS,CACT,QAAA,CAAS,mFAAmF,CAAA;AAAA,EAC/F,kBAAA,EAAoB,EACjB,MAAA,EAAO,CACP,UAAS,CACT,QAAA,EAAS,CACT,QAAA,CAAS,gGAAgG,CAAA;AAAA,EAC5G,cAAA,EAAgB,EACb,OAAA,EAAQ,CACR,UAAS,CACT,QAAA,EAAS,CACT,QAAA,CAAS,qHAAqH,CAAA;AAAA,EACjI,OAAA,EAAS,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,qCAAqC,CAAA;AAAA,EACxF,iBAAA,EAAmB,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,uCAAuC,CAAA;AAAA,EACpG,KAAA,EAAO,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,mCAAmC;AACtF,CAAC,EACA,IAAA,CAAK,EAAE,EAAA,EAAI,mBAAA,EAAqB,CAAA,CAChC,QAAA;AAAA,EACC;AACF,CAAA;AAIK,IAAM,iBAAA,GAAoB,EAC9B,MAAA,CAAO;AAAA,EACN,IAAI,CAAA,CACD,MAAA,EAAO,CACP,KAAA,CAAM,kBAAkB,CAAA,CACxB,QAAA;AAAA,IACC;AAAA,GACF;AAAA,EACF,IAAA,EAAM,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,6BAA6B,CAAA;AAAA,EAC9D,QAAA,EAAU,cAAA;AAAA,EACV,iBAAA,EAAmB,CAAA,CAChB,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,IACC;AAAA,GACF;AAAA,EACF,SAAS,CAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAAE,SAAS,mDAAmD,CAAA;AAAA,EAC5F,SAAS,CAAA,CACN,MAAA,GACA,QAAA,EAAS,CACT,SAAS,wFAAwF,CAAA;AAAA,EACpG,cAAA,EAAgB,qBAAqB,QAAA,EAAS;AAAA,EAC9C,MAAA,EAAQ,mBAAmB,QAAA,EAAS;AAAA,EACpC,OAAA,EAAS,kBAAkB,QAAA,EAAS;AAAA,EACpC,YAAA,EAAc,CAAA,CAAE,KAAA,CAAM,iBAAiB,EAAE,QAAA,EAAS;AAAA,EAClD,WAAA,EAAa,wBAAwB,QAAA,EAAS;AAAA,EAC9C,KAAA,EAAO,CAAA,CACJ,MAAA,CAAO,CAAA,CAAE,MAAA,EAAO,EAAG,CAAA,CAAE,OAAA,EAAS,CAAA,CAC9B,QAAA,EAAS,CACT,QAAA;AAAA,IACC;AAAA,GACF;AAAA,EACF,YAAY,CAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,SAAS,gCAAgC;AAC7E,CAAC,CAAA,CACA,KAAK,EAAE,EAAA,EAAI,eAAe,CAAA,CAC1B,SAAS,kGAAkG,CAAA;AAIvG,IAAM,mBAAA,GAAsB,CAAA,CAChC,IAAA,CAAK,CAAC,SAAA,EAAW,YAAA,EAAc,SAAA,EAAW,UAAU,CAAC,CAAA,CACrD,QAAA,CAAS,2DAA2D,CAAA;AAIhE,IAAM,mBAAA,GAAsB,EAChC,MAAA,CAAO;AAAA,EACN,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EACtB,QAAA,EAAU,cAAA;AAAA,EACV,MAAA,EAAQ,oBAAoB,QAAA,EAAS;AAAA,EACrC,KAAA,EAAO,CAAA,CAAE,MAAA,CAAO,CAAA,CAAE,MAAA,IAAU,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,QAAA,EAAS;AAAA,EAClD,IAAA,EAAM,EAAE,MAAA,EAAO,CAAE,UAAS,CAAE,QAAA,EAAS,CAAE,QAAA,CAAS,6EAA6E,CAAA;AAAA,EAC7H,OAAO,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAAW,QAAA;AAC/B,CAAC,EACA,IAAA,CAAK,EAAE,EAAA,EAAI,eAAA,EAAiB,CAAA,CAC5B,QAAA;AAAA,EACC;AACF,CAAA;AAIkC,EACjC,MAAA,CAAO;AAAA,EACN,aAAA,EAAe,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,uEAAuE,CAAA;AAAA,EACjH,GAAA,EAAK,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,2DAA6D,CAAA;AAAA,EAC7F,OAAA,EAAS,EACN,MAAA,EAAO,CACP,MAAM,kBAAkB,CAAA,CACxB,SAAS,0FAA0F,CAAA;AAAA,EACtG,QAAQ,CAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,SAAS,sCAAsC,CAAA;AAAA,EAC7E,aAAa,CAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,SAAS,sCAAsC,CAAA;AAAA,EAClF,SAAS,CAAA,CAAE,KAAA,CAAM,iBAAiB,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,EACzC,cAAA,EAAgB,CAAA,CAAE,KAAA,CAAM,mBAAmB,EAAE,QAAA;AAC/C,CAAC,EACA,IAAA,CAAK,EAAE,EAAA,EAAI,gBAAA,EAAkB,CAAA,CAC7B,QAAA;AAAA,EACC;AACF;;;ACvOK,IAAM,UAAA,GAAa,eAAA,CAAgB,cAAA,CAAe,OAAO;AACzD,IAAM,YAAA,GAAe,eAAA,CAAgB,gBAAA,CAAiB,OAAO;AAC7D,IAAM,mBAAA,GAAsB,eAAA,CAAgB,uBAAA,CAAwB,OAAO;AAC3E,IAAM,eAAA,GAAkB,eAAA,CAAgB,mBAAA,CAAoB,OAAO","file":"index.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * The sensor manifest is the instrument layer of the standard: DisclosureOS\n * records describe *what was observed*; a sensor manifest describes *the\n * hardware that produced the data* — per sensor, in enough structured detail\n * that a field mission or data drop from one organization is comparable,\n * replicable, and verifiable by everyone else.\n *\n * Design lineage: proposed by ELDÆON (disclosurefoundation/disclosureos#5) and\n * promoted into the framework as a foundation package. The manifest is the\n * standard's first standalone document type besides `Observation`: it is not a\n * per-observation extension slot — observations point at manifest entries via\n * `SensorReading.sensorRef` (`\"<org-slug>:<sensor-id>\"`).\n */\n\nconst KEBAB_CASE_PATTERN = /^[a-z0-9][a-z0-9-]*$/;\n\nexport const ModalitySchema = z\n .enum(['audio', 'electro_optical', 'radio_frequency', 'quantum', 'environmental', 'biometric'])\n .describe('Top-level sensing modality the sensor belongs to.');\n\nexport type Modality = z.infer<typeof ModalitySchema>;\n\nexport const TimeSourceSchema = z\n .enum(['atomic_clock', 'gps_disciplined', 'ntp', 'system', 'unknown'])\n .describe('Clock source that timestamps the sensor\\u2019s data.');\n\nexport type TimeSource = z.infer<typeof TimeSourceSchema>;\n\nexport const SensorTimingSchema = z\n .object({\n timeSource: TimeSourceSchema,\n timeUncertaintyNs: z\n .number()\n .nullable()\n .optional()\n .describe('Timestamp uncertainty in nanoseconds. Null = not yet characterized.'),\n })\n .meta({ id: 'SensorTiming' })\n .describe(\n 'Timing provenance. Timestamp error of even a few seconds confounds multi-station correlation, so the clock source must be declared, not assumed.',\n );\n\nexport type SensorTiming = z.infer<typeof SensorTimingSchema>;\n\nexport const RecordsMappingSchema = z\n .object({\n sensorType: z\n .string()\n .optional()\n .describe('The `@disclosureos/records` SensorType this sensor maps to.'),\n detectionMethod: z\n .string()\n .optional()\n .describe('The `@disclosureos/records` DetectionMethod this sensor maps to.'),\n proposedSensorType: z\n .boolean()\n .optional()\n .describe('True = sensorType is not in the records enum yet and is proposed by the publisher.'),\n proposedDetectionMethod: z\n .boolean()\n .optional()\n .describe('True = detectionMethod is not in the records enum yet and is proposed by the publisher.'),\n })\n .meta({ id: 'RecordsMapping' })\n .describe(\n 'How this sensor maps to the `SensorReading` vocabulary in `@disclosureos/records`. Values outside the records enums must carry the matching proposed* flag.',\n );\n\nexport type RecordsMapping = z.infer<typeof RecordsMappingSchema>;\n\nexport const RawDataSpecSchema = z\n .object({\n format: z\n .string()\n .optional()\n .describe('Raw-data file format, e.g. \"NDJSON.gz\", \"WAV\", \"MJPEG\", \"FITS\", \"CSV\".'),\n locatorPattern: z\n .string()\n .nullable()\n .optional()\n .describe('Storage key pattern or path convention for locating the raw files.'),\n sampleRateHz: z.number().nullable().optional().describe('Sample rate in Hz, where applicable.'),\n bitDepth: z.number().nullable().optional().describe('Sample bit depth, where applicable.'),\n })\n .meta({ id: 'RawDataSpec' })\n .describe(\n 'Raw-data format and locator. Supports a metadata-first architecture: circulate manifests widely, pull raw data on demand.',\n );\n\nexport type RawDataSpec = z.infer<typeof RawDataSpecSchema>;\n\nexport const UncertaintyTypeSchema = z\n .enum(['A', 'B'])\n .describe('GUM uncertainty evaluation type: A (statistical) or B (other means).');\n\nexport type UncertaintyType = z.infer<typeof UncertaintyTypeSchema>;\n\nexport const MeasurementUncertaintySchema = z\n .object({\n u_c: z.number().nullable().optional().describe('Combined standard uncertainty.'),\n U: z.number().nullable().optional().describe('Expanded uncertainty (= k \\u00d7 u_c).'),\n k: z.number().nullable().optional().describe('Coverage factor (2 \\u2248 95% confidence level).'),\n type: UncertaintyTypeSchema.nullable().optional(),\n })\n .meta({ id: 'MeasurementUncertainty' })\n .describe(\n 'GUM-style measurement uncertainty. Fields are nullable until an uncertainty budget exists — declaring \"unknown\" honestly is itself information.',\n );\n\nexport type MeasurementUncertainty = z.infer<typeof MeasurementUncertaintySchema>;\n\nexport const MeasurementSchema = z\n .object({\n name: z.string().min(1).describe('Measured quantity, e.g. \"differential_pressure\".'),\n unit: z.string().min(1).describe('UCUM-style unit string, e.g. \"Pa\", \"dB\", \"uT\", \"ppm\", \"/min\".'),\n uncertainty: MeasurementUncertaintySchema.optional(),\n })\n .meta({ id: 'Measurement' })\n .describe('One measured quantity with its unit and uncertainty.');\n\nexport type Measurement = z.infer<typeof MeasurementSchema>;\n\nexport const CalibrationStatusSchema = z\n .enum(['none', 'candidate_identified', 'in_practice', 'documented'])\n .describe(\n 'Calibration maturity gradient: none = no calibration; candidate_identified = a reference is named but not used; in_practice = a real method is performed but not fully budgeted; documented = method + uncertainty budget published.',\n );\n\nexport type CalibrationStatus = z.infer<typeof CalibrationStatusSchema>;\n\nexport const SensorCalibrationSchema = z\n .object({\n status: CalibrationStatusSchema,\n calibrated: z\n .boolean()\n .nullable()\n .optional()\n .describe('Coarse calibrated flag, mirroring `SensorReading.calibrated`. Null = undetermined.'),\n currentMethod: z\n .string()\n .nullable()\n .optional()\n .describe('What the operator actually does today. Null = no calibration currently performed.'),\n traceableReference: z\n .string()\n .nullable()\n .optional()\n .describe('Traceable reference, in use or identified as a candidate (e.g. \"GPS/UTC\", \"USGS/INTERMAGNET\").'),\n referenceInUse: z\n .boolean()\n .nullable()\n .optional()\n .describe('True = the traceable reference is part of current practice. False = identified candidate only. Null = undetermined.'),\n cadence: z.string().nullable().optional().describe('How often calibration is performed.'),\n uncertaintyBudget: z.string().nullable().optional().describe('Published uncertainty budget, if any.'),\n notes: z.string().nullable().optional().describe('Open questions or method caveats.'),\n })\n .meta({ id: 'SensorCalibration' })\n .describe(\n 'Calibration provenance. Deliberately separates what an operator actually does today from the reference it has identified; honest nulls are first-class, so calibration gaps stay visible and comparable across operators.',\n );\n\nexport type SensorCalibration = z.infer<typeof SensorCalibrationSchema>;\n\nexport const SensorEntrySchema = z\n .object({\n id: z\n .string()\n .regex(KEBAB_CASE_PATTERN)\n .describe(\n 'Stable kebab-case id, unique within the manifest; addressable from a record via `SensorReading.sensorRef` (\"<org-slug>:<sensor-id>\").',\n ),\n name: z.string().min(1).describe('Human-readable sensor name.'),\n modality: ModalitySchema,\n manufacturerModel: z\n .string()\n .optional()\n .describe(\n 'Hardware class descriptor. Publishers MAY withhold specific make/model identities and publish spec-level class descriptors instead (e.g. \"dual GM-tube counter\" rather than a product name).',\n ),\n inHouse: z.boolean().optional().describe('True if operator-built rather than off-the-shelf.'),\n compute: z\n .string()\n .optional()\n .describe('The compute unit this sensor is attached to, for platforms with several compute nodes.'),\n recordsMapping: RecordsMappingSchema.optional(),\n timing: SensorTimingSchema.optional(),\n rawData: RawDataSpecSchema.optional(),\n measurements: z.array(MeasurementSchema).optional(),\n calibration: SensorCalibrationSchema.optional(),\n specs: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Free-form hardware specifications from the operator\\u2019s spec sheet (resolution, range, sensitivity, interface, \\u2026). Keys vary by modality.',\n ),\n specSource: z.string().optional().describe('Provenance of the spec values.'),\n })\n .meta({ id: 'SensorEntry' })\n .describe('One sensor: its class, spec, timing, raw-data locator, measurements, and calibration provenance.');\n\nexport type SensorEntry = z.infer<typeof SensorEntrySchema>;\n\nexport const UpgradeStatusSchema = z\n .enum(['planned', 'evaluating', 'ordered', 'acquired'])\n .describe('Acquisition status of a declared future hardware upgrade.');\n\nexport type UpgradeStatus = z.infer<typeof UpgradeStatusSchema>;\n\nexport const FutureUpgradeSchema = z\n .object({\n name: z.string().min(1),\n modality: ModalitySchema,\n status: UpgradeStatusSchema.optional(),\n specs: z.record(z.string(), z.unknown()).optional(),\n link: z.string().nullable().optional().describe('Public product or reference page, where the publisher chooses to share one.'),\n notes: z.string().nullable().optional(),\n })\n .meta({ id: 'FutureUpgrade' })\n .describe(\n 'Planned hardware declared ahead of deployment so data consumers can anticipate new streams. Not part of the live sensor array.',\n );\n\nexport type FutureUpgrade = z.infer<typeof FutureUpgradeSchema>;\n\nexport const SensorManifestSchema = z\n .object({\n schemaVersion: z.string().min(1).describe('Version of the sensor-manifest schema this instance targets (SemVer).'),\n org: z.string().min(1).describe('Publishing organization, display form (e.g. \"ELD\\u00c6ON\").'),\n orgSlug: z\n .string()\n .regex(KEBAB_CASE_PATTERN)\n .describe('Stable lowercase slug for the publisher (e.g. \"eldaeon\"); the org half of a `sensorRef`.'),\n orgUrl: z.string().optional().describe('URL for the publishing organization.'),\n generatedAt: z.string().optional().describe('ISO date the manifest was generated.'),\n sensors: z.array(SensorEntrySchema).min(1),\n futureUpgrades: z.array(FutureUpgradeSchema).optional(),\n })\n .meta({ id: 'SensorManifest' })\n .describe(\n 'A published catalog of one organization\\u2019s detection hardware. Any operator — vendor, research group, or institution — publishes its own manifest against this schema so datasets from different sensor arrays can be compared directly.',\n );\n\nexport type SensorManifest = z.infer<typeof SensorManifestSchema>;\n","import { createEnumGuard } from '@disclosureos/records/shared';\nimport {\n ModalitySchema,\n TimeSourceSchema,\n CalibrationStatusSchema,\n UpgradeStatusSchema,\n} from '../manifest/types';\n\n// Enum guards are built from each schema's `.options` (a plain string tuple)\n// rather than the Zod schema itself: passing a Zod type across the package\n// boundary collides with Zod's internal version brand, whereas the literal\n// tuple is brand-free and still schema-derived.\nexport const isModality = createEnumGuard(ModalitySchema.options);\nexport const isTimeSource = createEnumGuard(TimeSourceSchema.options);\nexport const isCalibrationStatus = createEnumGuard(CalibrationStatusSchema.options);\nexport const isUpgradeStatus = createEnumGuard(UpgradeStatusSchema.options);\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export { CalibrationStatus, CalibrationStatusSchema, FutureUpgrade, FutureUpgradeSchema, Measurement, MeasurementSchema, MeasurementUncertainty, MeasurementUncertaintySchema, Modality, ModalitySchema, RawDataSpec, RawDataSpecSchema, RecordsMapping, RecordsMappingSchema, SensorCalibration, SensorCalibrationSchema, SensorEntry, SensorEntrySchema, SensorManifest, SensorManifestSchema, SensorTiming, SensorTimingSchema, TimeSource, TimeSourceSchema, UncertaintyType, UncertaintyTypeSchema, UpgradeStatus, UpgradeStatusSchema } from './manifest/index.js';
|
|
2
|
+
export { CALIBRATION_STATUSES, MODALITIES, TIME_SOURCES, UNCERTAINTY_TYPES, UPGRADE_STATUSES } from './constants/index.js';
|
|
3
|
+
export { CALIBRATION_STATUS_DESCRIPTIONS, CALIBRATION_STATUS_LABELS, MODALITY_LABELS, TIME_SOURCE_LABELS, UPGRADE_STATUS_LABELS } from './labels/index.js';
|
|
4
|
+
export { isCalibrationStatus, isModality, isTimeSource, isUpgradeStatus } from './guards/index.js';
|
|
5
|
+
export { createSensorEntry, createSensorManifest } from './factories/index.js';
|
|
6
|
+
export { formatCalibrationStatus, formatModality, formatSensorEntry, formatSensorManifest } from './formatters/index.js';
|
|
7
|
+
export { validateSensorManifest } from './validators/index.js';
|
|
8
|
+
import 'zod';
|
|
9
|
+
import '@disclosureos/records/shared';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Version of the emitted JSON Schema artifact. Bump on any intentional change
|
|
13
|
+
* to the manifest shape; the committed `schema/sensor-manifest.schema.json` and
|
|
14
|
+
* the drift test (`src/__tests__/schema.test.ts`) keep this honest.
|
|
15
|
+
*/
|
|
16
|
+
declare const INSTRUMENTS_SCHEMA_VERSION = "1.0.0";
|
|
17
|
+
declare const INSTRUMENTS_SCHEMA_ID: string;
|
|
18
|
+
/**
|
|
19
|
+
* Emit the canonical JSON Schema (draft 2020-12) for {@link SensorManifestSchema}.
|
|
20
|
+
* Unlike the satellite slot schemas, this is a standalone document schema — a
|
|
21
|
+
* manifest is published on its own, not composed into `Observation`.
|
|
22
|
+
*/
|
|
23
|
+
declare function instrumentsJsonSchema(): Record<string, unknown>;
|
|
24
|
+
|
|
25
|
+
export { INSTRUMENTS_SCHEMA_ID, INSTRUMENTS_SCHEMA_VERSION, instrumentsJsonSchema };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createEnumGuard, schemaId, jsonSchemaEnvelope, validateWith } from '@disclosureos/records/shared';
|
|
3
|
+
import { SENSOR_TYPES, DETECTION_METHODS } from '@disclosureos/records/constants';
|
|
4
|
+
|
|
5
|
+
// src/manifest/types.ts
|
|
6
|
+
var KEBAB_CASE_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
7
|
+
var ModalitySchema = z.enum(["audio", "electro_optical", "radio_frequency", "quantum", "environmental", "biometric"]).describe("Top-level sensing modality the sensor belongs to.");
|
|
8
|
+
var TimeSourceSchema = z.enum(["atomic_clock", "gps_disciplined", "ntp", "system", "unknown"]).describe("Clock source that timestamps the sensor\u2019s data.");
|
|
9
|
+
var SensorTimingSchema = z.object({
|
|
10
|
+
timeSource: TimeSourceSchema,
|
|
11
|
+
timeUncertaintyNs: z.number().nullable().optional().describe("Timestamp uncertainty in nanoseconds. Null = not yet characterized.")
|
|
12
|
+
}).meta({ id: "SensorTiming" }).describe(
|
|
13
|
+
"Timing provenance. Timestamp error of even a few seconds confounds multi-station correlation, so the clock source must be declared, not assumed."
|
|
14
|
+
);
|
|
15
|
+
var RecordsMappingSchema = z.object({
|
|
16
|
+
sensorType: z.string().optional().describe("The `@disclosureos/records` SensorType this sensor maps to."),
|
|
17
|
+
detectionMethod: z.string().optional().describe("The `@disclosureos/records` DetectionMethod this sensor maps to."),
|
|
18
|
+
proposedSensorType: z.boolean().optional().describe("True = sensorType is not in the records enum yet and is proposed by the publisher."),
|
|
19
|
+
proposedDetectionMethod: z.boolean().optional().describe("True = detectionMethod is not in the records enum yet and is proposed by the publisher.")
|
|
20
|
+
}).meta({ id: "RecordsMapping" }).describe(
|
|
21
|
+
"How this sensor maps to the `SensorReading` vocabulary in `@disclosureos/records`. Values outside the records enums must carry the matching proposed* flag."
|
|
22
|
+
);
|
|
23
|
+
var RawDataSpecSchema = z.object({
|
|
24
|
+
format: z.string().optional().describe('Raw-data file format, e.g. "NDJSON.gz", "WAV", "MJPEG", "FITS", "CSV".'),
|
|
25
|
+
locatorPattern: z.string().nullable().optional().describe("Storage key pattern or path convention for locating the raw files."),
|
|
26
|
+
sampleRateHz: z.number().nullable().optional().describe("Sample rate in Hz, where applicable."),
|
|
27
|
+
bitDepth: z.number().nullable().optional().describe("Sample bit depth, where applicable.")
|
|
28
|
+
}).meta({ id: "RawDataSpec" }).describe(
|
|
29
|
+
"Raw-data format and locator. Supports a metadata-first architecture: circulate manifests widely, pull raw data on demand."
|
|
30
|
+
);
|
|
31
|
+
var UncertaintyTypeSchema = z.enum(["A", "B"]).describe("GUM uncertainty evaluation type: A (statistical) or B (other means).");
|
|
32
|
+
var MeasurementUncertaintySchema = z.object({
|
|
33
|
+
u_c: z.number().nullable().optional().describe("Combined standard uncertainty."),
|
|
34
|
+
U: z.number().nullable().optional().describe("Expanded uncertainty (= k \xD7 u_c)."),
|
|
35
|
+
k: z.number().nullable().optional().describe("Coverage factor (2 \u2248 95% confidence level)."),
|
|
36
|
+
type: UncertaintyTypeSchema.nullable().optional()
|
|
37
|
+
}).meta({ id: "MeasurementUncertainty" }).describe(
|
|
38
|
+
'GUM-style measurement uncertainty. Fields are nullable until an uncertainty budget exists \u2014 declaring "unknown" honestly is itself information.'
|
|
39
|
+
);
|
|
40
|
+
var MeasurementSchema = z.object({
|
|
41
|
+
name: z.string().min(1).describe('Measured quantity, e.g. "differential_pressure".'),
|
|
42
|
+
unit: z.string().min(1).describe('UCUM-style unit string, e.g. "Pa", "dB", "uT", "ppm", "/min".'),
|
|
43
|
+
uncertainty: MeasurementUncertaintySchema.optional()
|
|
44
|
+
}).meta({ id: "Measurement" }).describe("One measured quantity with its unit and uncertainty.");
|
|
45
|
+
var CalibrationStatusSchema = z.enum(["none", "candidate_identified", "in_practice", "documented"]).describe(
|
|
46
|
+
"Calibration maturity gradient: none = no calibration; candidate_identified = a reference is named but not used; in_practice = a real method is performed but not fully budgeted; documented = method + uncertainty budget published."
|
|
47
|
+
);
|
|
48
|
+
var SensorCalibrationSchema = z.object({
|
|
49
|
+
status: CalibrationStatusSchema,
|
|
50
|
+
calibrated: z.boolean().nullable().optional().describe("Coarse calibrated flag, mirroring `SensorReading.calibrated`. Null = undetermined."),
|
|
51
|
+
currentMethod: z.string().nullable().optional().describe("What the operator actually does today. Null = no calibration currently performed."),
|
|
52
|
+
traceableReference: z.string().nullable().optional().describe('Traceable reference, in use or identified as a candidate (e.g. "GPS/UTC", "USGS/INTERMAGNET").'),
|
|
53
|
+
referenceInUse: z.boolean().nullable().optional().describe("True = the traceable reference is part of current practice. False = identified candidate only. Null = undetermined."),
|
|
54
|
+
cadence: z.string().nullable().optional().describe("How often calibration is performed."),
|
|
55
|
+
uncertaintyBudget: z.string().nullable().optional().describe("Published uncertainty budget, if any."),
|
|
56
|
+
notes: z.string().nullable().optional().describe("Open questions or method caveats.")
|
|
57
|
+
}).meta({ id: "SensorCalibration" }).describe(
|
|
58
|
+
"Calibration provenance. Deliberately separates what an operator actually does today from the reference it has identified; honest nulls are first-class, so calibration gaps stay visible and comparable across operators."
|
|
59
|
+
);
|
|
60
|
+
var SensorEntrySchema = z.object({
|
|
61
|
+
id: z.string().regex(KEBAB_CASE_PATTERN).describe(
|
|
62
|
+
'Stable kebab-case id, unique within the manifest; addressable from a record via `SensorReading.sensorRef` ("<org-slug>:<sensor-id>").'
|
|
63
|
+
),
|
|
64
|
+
name: z.string().min(1).describe("Human-readable sensor name."),
|
|
65
|
+
modality: ModalitySchema,
|
|
66
|
+
manufacturerModel: z.string().optional().describe(
|
|
67
|
+
'Hardware class descriptor. Publishers MAY withhold specific make/model identities and publish spec-level class descriptors instead (e.g. "dual GM-tube counter" rather than a product name).'
|
|
68
|
+
),
|
|
69
|
+
inHouse: z.boolean().optional().describe("True if operator-built rather than off-the-shelf."),
|
|
70
|
+
compute: z.string().optional().describe("The compute unit this sensor is attached to, for platforms with several compute nodes."),
|
|
71
|
+
recordsMapping: RecordsMappingSchema.optional(),
|
|
72
|
+
timing: SensorTimingSchema.optional(),
|
|
73
|
+
rawData: RawDataSpecSchema.optional(),
|
|
74
|
+
measurements: z.array(MeasurementSchema).optional(),
|
|
75
|
+
calibration: SensorCalibrationSchema.optional(),
|
|
76
|
+
specs: z.record(z.string(), z.unknown()).optional().describe(
|
|
77
|
+
"Free-form hardware specifications from the operator\u2019s spec sheet (resolution, range, sensitivity, interface, \u2026). Keys vary by modality."
|
|
78
|
+
),
|
|
79
|
+
specSource: z.string().optional().describe("Provenance of the spec values.")
|
|
80
|
+
}).meta({ id: "SensorEntry" }).describe("One sensor: its class, spec, timing, raw-data locator, measurements, and calibration provenance.");
|
|
81
|
+
var UpgradeStatusSchema = z.enum(["planned", "evaluating", "ordered", "acquired"]).describe("Acquisition status of a declared future hardware upgrade.");
|
|
82
|
+
var FutureUpgradeSchema = z.object({
|
|
83
|
+
name: z.string().min(1),
|
|
84
|
+
modality: ModalitySchema,
|
|
85
|
+
status: UpgradeStatusSchema.optional(),
|
|
86
|
+
specs: z.record(z.string(), z.unknown()).optional(),
|
|
87
|
+
link: z.string().nullable().optional().describe("Public product or reference page, where the publisher chooses to share one."),
|
|
88
|
+
notes: z.string().nullable().optional()
|
|
89
|
+
}).meta({ id: "FutureUpgrade" }).describe(
|
|
90
|
+
"Planned hardware declared ahead of deployment so data consumers can anticipate new streams. Not part of the live sensor array."
|
|
91
|
+
);
|
|
92
|
+
var SensorManifestSchema = z.object({
|
|
93
|
+
schemaVersion: z.string().min(1).describe("Version of the sensor-manifest schema this instance targets (SemVer)."),
|
|
94
|
+
org: z.string().min(1).describe('Publishing organization, display form (e.g. "ELD\xC6ON").'),
|
|
95
|
+
orgSlug: z.string().regex(KEBAB_CASE_PATTERN).describe('Stable lowercase slug for the publisher (e.g. "eldaeon"); the org half of a `sensorRef`.'),
|
|
96
|
+
orgUrl: z.string().optional().describe("URL for the publishing organization."),
|
|
97
|
+
generatedAt: z.string().optional().describe("ISO date the manifest was generated."),
|
|
98
|
+
sensors: z.array(SensorEntrySchema).min(1),
|
|
99
|
+
futureUpgrades: z.array(FutureUpgradeSchema).optional()
|
|
100
|
+
}).meta({ id: "SensorManifest" }).describe(
|
|
101
|
+
"A published catalog of one organization\u2019s detection hardware. Any operator \u2014 vendor, research group, or institution \u2014 publishes its own manifest against this schema so datasets from different sensor arrays can be compared directly."
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// src/constants/index.ts
|
|
105
|
+
var MODALITIES = ModalitySchema.options;
|
|
106
|
+
var TIME_SOURCES = TimeSourceSchema.options;
|
|
107
|
+
var CALIBRATION_STATUSES = CalibrationStatusSchema.options;
|
|
108
|
+
var UPGRADE_STATUSES = UpgradeStatusSchema.options;
|
|
109
|
+
var UNCERTAINTY_TYPES = UncertaintyTypeSchema.options;
|
|
110
|
+
|
|
111
|
+
// src/labels/index.ts
|
|
112
|
+
var MODALITY_LABELS = {
|
|
113
|
+
audio: "Audio",
|
|
114
|
+
electro_optical: "Electro-Optical",
|
|
115
|
+
radio_frequency: "Radio Frequency",
|
|
116
|
+
quantum: "Quantum",
|
|
117
|
+
environmental: "Environmental",
|
|
118
|
+
biometric: "Biometric"
|
|
119
|
+
};
|
|
120
|
+
var TIME_SOURCE_LABELS = {
|
|
121
|
+
atomic_clock: "Atomic Clock",
|
|
122
|
+
gps_disciplined: "GPS-Disciplined",
|
|
123
|
+
ntp: "NTP",
|
|
124
|
+
system: "System Clock",
|
|
125
|
+
unknown: "Unknown"
|
|
126
|
+
};
|
|
127
|
+
var CALIBRATION_STATUS_LABELS = {
|
|
128
|
+
none: "None",
|
|
129
|
+
candidate_identified: "Candidate Identified",
|
|
130
|
+
in_practice: "In Practice",
|
|
131
|
+
documented: "Documented"
|
|
132
|
+
};
|
|
133
|
+
var CALIBRATION_STATUS_DESCRIPTIONS = {
|
|
134
|
+
none: "No calibration is performed. Declared honestly, this is itself useful information.",
|
|
135
|
+
candidate_identified: "A traceable reference has been named but is not yet part of practice.",
|
|
136
|
+
in_practice: "A real calibration method is performed today, but no full uncertainty budget exists.",
|
|
137
|
+
documented: "The calibration method and its uncertainty budget are published."
|
|
138
|
+
};
|
|
139
|
+
var UPGRADE_STATUS_LABELS = {
|
|
140
|
+
planned: "Planned",
|
|
141
|
+
evaluating: "Evaluating",
|
|
142
|
+
ordered: "Ordered",
|
|
143
|
+
acquired: "Acquired"
|
|
144
|
+
};
|
|
145
|
+
var isModality = createEnumGuard(ModalitySchema.options);
|
|
146
|
+
var isTimeSource = createEnumGuard(TimeSourceSchema.options);
|
|
147
|
+
var isCalibrationStatus = createEnumGuard(CalibrationStatusSchema.options);
|
|
148
|
+
var isUpgradeStatus = createEnumGuard(UpgradeStatusSchema.options);
|
|
149
|
+
var INSTRUMENTS_SCHEMA_VERSION = "1.0.0";
|
|
150
|
+
var INSTRUMENTS_SCHEMA_ID = schemaId(
|
|
151
|
+
"instruments",
|
|
152
|
+
"sensor-manifest",
|
|
153
|
+
INSTRUMENTS_SCHEMA_VERSION
|
|
154
|
+
);
|
|
155
|
+
function instrumentsJsonSchema() {
|
|
156
|
+
const schema = z.toJSONSchema(SensorManifestSchema, { target: "draft-2020-12" });
|
|
157
|
+
return jsonSchemaEnvelope(schema, {
|
|
158
|
+
id: INSTRUMENTS_SCHEMA_ID,
|
|
159
|
+
version: INSTRUMENTS_SCHEMA_VERSION
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/factories/index.ts
|
|
164
|
+
function createSensorEntry(id, name, modality, options) {
|
|
165
|
+
return { id, name, modality, ...options };
|
|
166
|
+
}
|
|
167
|
+
function createSensorManifest(org, orgSlug, sensors, options) {
|
|
168
|
+
return {
|
|
169
|
+
schemaVersion: INSTRUMENTS_SCHEMA_VERSION,
|
|
170
|
+
org,
|
|
171
|
+
orgSlug,
|
|
172
|
+
sensors,
|
|
173
|
+
...options
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/formatters/index.ts
|
|
178
|
+
function formatModality(modality) {
|
|
179
|
+
return MODALITY_LABELS[modality];
|
|
180
|
+
}
|
|
181
|
+
function formatCalibrationStatus(status) {
|
|
182
|
+
return CALIBRATION_STATUS_LABELS[status];
|
|
183
|
+
}
|
|
184
|
+
function formatSensorEntry(sensor) {
|
|
185
|
+
const calibration = sensor.calibration ? ` \u2014 calibration: ${formatCalibrationStatus(sensor.calibration.status)}` : "";
|
|
186
|
+
return `${sensor.name} (${formatModality(sensor.modality)})${calibration}`;
|
|
187
|
+
}
|
|
188
|
+
function formatSensorManifest(manifest) {
|
|
189
|
+
const modalityCount = new Set(manifest.sensors.map((sensor) => sensor.modality)).size;
|
|
190
|
+
const sensorCount = manifest.sensors.length;
|
|
191
|
+
const upgrades = manifest.futureUpgrades?.length ?? 0;
|
|
192
|
+
const upgradeSuffix = upgrades > 0 ? `, ${upgrades} future upgrade${upgrades === 1 ? "" : "s"}` : "";
|
|
193
|
+
return `${manifest.org} \u2014 ${sensorCount} sensor${sensorCount === 1 ? "" : "s"} across ${modalityCount} modalit${modalityCount === 1 ? "y" : "ies"}${upgradeSuffix}`;
|
|
194
|
+
}
|
|
195
|
+
var KNOWN_SENSOR_TYPES = new Set(SENSOR_TYPES);
|
|
196
|
+
var KNOWN_DETECTION_METHODS = new Set(DETECTION_METHODS);
|
|
197
|
+
function validateSensorManifest(value) {
|
|
198
|
+
const issues = validateWith(SensorManifestSchema, value);
|
|
199
|
+
if (issues.length > 0) return issues;
|
|
200
|
+
const manifest = value;
|
|
201
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
202
|
+
manifest.sensors.forEach((sensor, index) => {
|
|
203
|
+
const path = `sensors.${index}`;
|
|
204
|
+
if (seenIds.has(sensor.id)) {
|
|
205
|
+
issues.push({ path: `${path}.id`, message: `Duplicate sensor id "${sensor.id}".` });
|
|
206
|
+
}
|
|
207
|
+
seenIds.add(sensor.id);
|
|
208
|
+
const mapping = sensor.recordsMapping;
|
|
209
|
+
if (!mapping) return;
|
|
210
|
+
if (mapping.sensorType !== void 0 && !KNOWN_SENSOR_TYPES.has(mapping.sensorType) && mapping.proposedSensorType !== true) {
|
|
211
|
+
issues.push({
|
|
212
|
+
path: `${path}.recordsMapping.sensorType`,
|
|
213
|
+
message: `"${mapping.sensorType}" is not a records SensorType; flag it with proposedSensorType: true or use a value from the enum.`
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
if (mapping.detectionMethod !== void 0 && !KNOWN_DETECTION_METHODS.has(mapping.detectionMethod) && mapping.proposedDetectionMethod !== true) {
|
|
217
|
+
issues.push({
|
|
218
|
+
path: `${path}.recordsMapping.detectionMethod`,
|
|
219
|
+
message: `"${mapping.detectionMethod}" is not a records DetectionMethod; flag it with proposedDetectionMethod: true or use a value from the enum.`
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
return issues;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export { CALIBRATION_STATUSES, CALIBRATION_STATUS_DESCRIPTIONS, CALIBRATION_STATUS_LABELS, CalibrationStatusSchema, FutureUpgradeSchema, INSTRUMENTS_SCHEMA_ID, INSTRUMENTS_SCHEMA_VERSION, MODALITIES, MODALITY_LABELS, MeasurementSchema, MeasurementUncertaintySchema, ModalitySchema, RawDataSpecSchema, RecordsMappingSchema, SensorCalibrationSchema, SensorEntrySchema, SensorManifestSchema, SensorTimingSchema, TIME_SOURCES, TIME_SOURCE_LABELS, TimeSourceSchema, UNCERTAINTY_TYPES, UPGRADE_STATUSES, UPGRADE_STATUS_LABELS, UncertaintyTypeSchema, UpgradeStatusSchema, createSensorEntry, createSensorManifest, formatCalibrationStatus, formatModality, formatSensorEntry, formatSensorManifest, instrumentsJsonSchema, isCalibrationStatus, isModality, isTimeSource, isUpgradeStatus, validateSensorManifest };
|
|
227
|
+
//# sourceMappingURL=index.js.map
|
|
228
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/manifest/types.ts","../src/constants/index.ts","../src/labels/index.ts","../src/guards/index.ts","../src/schema.ts","../src/factories/index.ts","../src/formatters/index.ts","../src/validators/index.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * The sensor manifest is the instrument layer of the standard: DisclosureOS\n * records describe *what was observed*; a sensor manifest describes *the\n * hardware that produced the data* — per sensor, in enough structured detail\n * that a field mission or data drop from one organization is comparable,\n * replicable, and verifiable by everyone else.\n *\n * Design lineage: proposed by ELDÆON (disclosurefoundation/disclosureos#5) and\n * promoted into the framework as a foundation package. The manifest is the\n * standard's first standalone document type besides `Observation`: it is not a\n * per-observation extension slot — observations point at manifest entries via\n * `SensorReading.sensorRef` (`\"<org-slug>:<sensor-id>\"`).\n */\n\nconst KEBAB_CASE_PATTERN = /^[a-z0-9][a-z0-9-]*$/;\n\nexport const ModalitySchema = z\n .enum(['audio', 'electro_optical', 'radio_frequency', 'quantum', 'environmental', 'biometric'])\n .describe('Top-level sensing modality the sensor belongs to.');\n\nexport type Modality = z.infer<typeof ModalitySchema>;\n\nexport const TimeSourceSchema = z\n .enum(['atomic_clock', 'gps_disciplined', 'ntp', 'system', 'unknown'])\n .describe('Clock source that timestamps the sensor\\u2019s data.');\n\nexport type TimeSource = z.infer<typeof TimeSourceSchema>;\n\nexport const SensorTimingSchema = z\n .object({\n timeSource: TimeSourceSchema,\n timeUncertaintyNs: z\n .number()\n .nullable()\n .optional()\n .describe('Timestamp uncertainty in nanoseconds. Null = not yet characterized.'),\n })\n .meta({ id: 'SensorTiming' })\n .describe(\n 'Timing provenance. Timestamp error of even a few seconds confounds multi-station correlation, so the clock source must be declared, not assumed.',\n );\n\nexport type SensorTiming = z.infer<typeof SensorTimingSchema>;\n\nexport const RecordsMappingSchema = z\n .object({\n sensorType: z\n .string()\n .optional()\n .describe('The `@disclosureos/records` SensorType this sensor maps to.'),\n detectionMethod: z\n .string()\n .optional()\n .describe('The `@disclosureos/records` DetectionMethod this sensor maps to.'),\n proposedSensorType: z\n .boolean()\n .optional()\n .describe('True = sensorType is not in the records enum yet and is proposed by the publisher.'),\n proposedDetectionMethod: z\n .boolean()\n .optional()\n .describe('True = detectionMethod is not in the records enum yet and is proposed by the publisher.'),\n })\n .meta({ id: 'RecordsMapping' })\n .describe(\n 'How this sensor maps to the `SensorReading` vocabulary in `@disclosureos/records`. Values outside the records enums must carry the matching proposed* flag.',\n );\n\nexport type RecordsMapping = z.infer<typeof RecordsMappingSchema>;\n\nexport const RawDataSpecSchema = z\n .object({\n format: z\n .string()\n .optional()\n .describe('Raw-data file format, e.g. \"NDJSON.gz\", \"WAV\", \"MJPEG\", \"FITS\", \"CSV\".'),\n locatorPattern: z\n .string()\n .nullable()\n .optional()\n .describe('Storage key pattern or path convention for locating the raw files.'),\n sampleRateHz: z.number().nullable().optional().describe('Sample rate in Hz, where applicable.'),\n bitDepth: z.number().nullable().optional().describe('Sample bit depth, where applicable.'),\n })\n .meta({ id: 'RawDataSpec' })\n .describe(\n 'Raw-data format and locator. Supports a metadata-first architecture: circulate manifests widely, pull raw data on demand.',\n );\n\nexport type RawDataSpec = z.infer<typeof RawDataSpecSchema>;\n\nexport const UncertaintyTypeSchema = z\n .enum(['A', 'B'])\n .describe('GUM uncertainty evaluation type: A (statistical) or B (other means).');\n\nexport type UncertaintyType = z.infer<typeof UncertaintyTypeSchema>;\n\nexport const MeasurementUncertaintySchema = z\n .object({\n u_c: z.number().nullable().optional().describe('Combined standard uncertainty.'),\n U: z.number().nullable().optional().describe('Expanded uncertainty (= k \\u00d7 u_c).'),\n k: z.number().nullable().optional().describe('Coverage factor (2 \\u2248 95% confidence level).'),\n type: UncertaintyTypeSchema.nullable().optional(),\n })\n .meta({ id: 'MeasurementUncertainty' })\n .describe(\n 'GUM-style measurement uncertainty. Fields are nullable until an uncertainty budget exists — declaring \"unknown\" honestly is itself information.',\n );\n\nexport type MeasurementUncertainty = z.infer<typeof MeasurementUncertaintySchema>;\n\nexport const MeasurementSchema = z\n .object({\n name: z.string().min(1).describe('Measured quantity, e.g. \"differential_pressure\".'),\n unit: z.string().min(1).describe('UCUM-style unit string, e.g. \"Pa\", \"dB\", \"uT\", \"ppm\", \"/min\".'),\n uncertainty: MeasurementUncertaintySchema.optional(),\n })\n .meta({ id: 'Measurement' })\n .describe('One measured quantity with its unit and uncertainty.');\n\nexport type Measurement = z.infer<typeof MeasurementSchema>;\n\nexport const CalibrationStatusSchema = z\n .enum(['none', 'candidate_identified', 'in_practice', 'documented'])\n .describe(\n 'Calibration maturity gradient: none = no calibration; candidate_identified = a reference is named but not used; in_practice = a real method is performed but not fully budgeted; documented = method + uncertainty budget published.',\n );\n\nexport type CalibrationStatus = z.infer<typeof CalibrationStatusSchema>;\n\nexport const SensorCalibrationSchema = z\n .object({\n status: CalibrationStatusSchema,\n calibrated: z\n .boolean()\n .nullable()\n .optional()\n .describe('Coarse calibrated flag, mirroring `SensorReading.calibrated`. Null = undetermined.'),\n currentMethod: z\n .string()\n .nullable()\n .optional()\n .describe('What the operator actually does today. Null = no calibration currently performed.'),\n traceableReference: z\n .string()\n .nullable()\n .optional()\n .describe('Traceable reference, in use or identified as a candidate (e.g. \"GPS/UTC\", \"USGS/INTERMAGNET\").'),\n referenceInUse: z\n .boolean()\n .nullable()\n .optional()\n .describe('True = the traceable reference is part of current practice. False = identified candidate only. Null = undetermined.'),\n cadence: z.string().nullable().optional().describe('How often calibration is performed.'),\n uncertaintyBudget: z.string().nullable().optional().describe('Published uncertainty budget, if any.'),\n notes: z.string().nullable().optional().describe('Open questions or method caveats.'),\n })\n .meta({ id: 'SensorCalibration' })\n .describe(\n 'Calibration provenance. Deliberately separates what an operator actually does today from the reference it has identified; honest nulls are first-class, so calibration gaps stay visible and comparable across operators.',\n );\n\nexport type SensorCalibration = z.infer<typeof SensorCalibrationSchema>;\n\nexport const SensorEntrySchema = z\n .object({\n id: z\n .string()\n .regex(KEBAB_CASE_PATTERN)\n .describe(\n 'Stable kebab-case id, unique within the manifest; addressable from a record via `SensorReading.sensorRef` (\"<org-slug>:<sensor-id>\").',\n ),\n name: z.string().min(1).describe('Human-readable sensor name.'),\n modality: ModalitySchema,\n manufacturerModel: z\n .string()\n .optional()\n .describe(\n 'Hardware class descriptor. Publishers MAY withhold specific make/model identities and publish spec-level class descriptors instead (e.g. \"dual GM-tube counter\" rather than a product name).',\n ),\n inHouse: z.boolean().optional().describe('True if operator-built rather than off-the-shelf.'),\n compute: z\n .string()\n .optional()\n .describe('The compute unit this sensor is attached to, for platforms with several compute nodes.'),\n recordsMapping: RecordsMappingSchema.optional(),\n timing: SensorTimingSchema.optional(),\n rawData: RawDataSpecSchema.optional(),\n measurements: z.array(MeasurementSchema).optional(),\n calibration: SensorCalibrationSchema.optional(),\n specs: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Free-form hardware specifications from the operator\\u2019s spec sheet (resolution, range, sensitivity, interface, \\u2026). Keys vary by modality.',\n ),\n specSource: z.string().optional().describe('Provenance of the spec values.'),\n })\n .meta({ id: 'SensorEntry' })\n .describe('One sensor: its class, spec, timing, raw-data locator, measurements, and calibration provenance.');\n\nexport type SensorEntry = z.infer<typeof SensorEntrySchema>;\n\nexport const UpgradeStatusSchema = z\n .enum(['planned', 'evaluating', 'ordered', 'acquired'])\n .describe('Acquisition status of a declared future hardware upgrade.');\n\nexport type UpgradeStatus = z.infer<typeof UpgradeStatusSchema>;\n\nexport const FutureUpgradeSchema = z\n .object({\n name: z.string().min(1),\n modality: ModalitySchema,\n status: UpgradeStatusSchema.optional(),\n specs: z.record(z.string(), z.unknown()).optional(),\n link: z.string().nullable().optional().describe('Public product or reference page, where the publisher chooses to share one.'),\n notes: z.string().nullable().optional(),\n })\n .meta({ id: 'FutureUpgrade' })\n .describe(\n 'Planned hardware declared ahead of deployment so data consumers can anticipate new streams. Not part of the live sensor array.',\n );\n\nexport type FutureUpgrade = z.infer<typeof FutureUpgradeSchema>;\n\nexport const SensorManifestSchema = z\n .object({\n schemaVersion: z.string().min(1).describe('Version of the sensor-manifest schema this instance targets (SemVer).'),\n org: z.string().min(1).describe('Publishing organization, display form (e.g. \"ELD\\u00c6ON\").'),\n orgSlug: z\n .string()\n .regex(KEBAB_CASE_PATTERN)\n .describe('Stable lowercase slug for the publisher (e.g. \"eldaeon\"); the org half of a `sensorRef`.'),\n orgUrl: z.string().optional().describe('URL for the publishing organization.'),\n generatedAt: z.string().optional().describe('ISO date the manifest was generated.'),\n sensors: z.array(SensorEntrySchema).min(1),\n futureUpgrades: z.array(FutureUpgradeSchema).optional(),\n })\n .meta({ id: 'SensorManifest' })\n .describe(\n 'A published catalog of one organization\\u2019s detection hardware. Any operator — vendor, research group, or institution — publishes its own manifest against this schema so datasets from different sensor arrays can be compared directly.',\n );\n\nexport type SensorManifest = z.infer<typeof SensorManifestSchema>;\n","import {\n ModalitySchema,\n TimeSourceSchema,\n CalibrationStatusSchema,\n UpgradeStatusSchema,\n UncertaintyTypeSchema,\n} from '../manifest/types';\n\nexport const MODALITIES = ModalitySchema.options;\nexport const TIME_SOURCES = TimeSourceSchema.options;\nexport const CALIBRATION_STATUSES = CalibrationStatusSchema.options;\nexport const UPGRADE_STATUSES = UpgradeStatusSchema.options;\nexport const UNCERTAINTY_TYPES = UncertaintyTypeSchema.options;\n","import type { Modality, TimeSource, CalibrationStatus, UpgradeStatus } from '../manifest/types';\n\nexport const MODALITY_LABELS: Record<Modality, string> = {\n audio: 'Audio',\n electro_optical: 'Electro-Optical',\n radio_frequency: 'Radio Frequency',\n quantum: 'Quantum',\n environmental: 'Environmental',\n biometric: 'Biometric',\n};\n\nexport const TIME_SOURCE_LABELS: Record<TimeSource, string> = {\n atomic_clock: 'Atomic Clock',\n gps_disciplined: 'GPS-Disciplined',\n ntp: 'NTP',\n system: 'System Clock',\n unknown: 'Unknown',\n};\n\nexport const CALIBRATION_STATUS_LABELS: Record<CalibrationStatus, string> = {\n none: 'None',\n candidate_identified: 'Candidate Identified',\n in_practice: 'In Practice',\n documented: 'Documented',\n};\n\n/** What each rung of the calibration maturity gradient means for a data consumer. */\nexport const CALIBRATION_STATUS_DESCRIPTIONS: Record<CalibrationStatus, string> = {\n none: 'No calibration is performed. Declared honestly, this is itself useful information.',\n candidate_identified: 'A traceable reference has been named but is not yet part of practice.',\n in_practice: 'A real calibration method is performed today, but no full uncertainty budget exists.',\n documented: 'The calibration method and its uncertainty budget are published.',\n};\n\nexport const UPGRADE_STATUS_LABELS: Record<UpgradeStatus, string> = {\n planned: 'Planned',\n evaluating: 'Evaluating',\n ordered: 'Ordered',\n acquired: 'Acquired',\n};\n","import { createEnumGuard } from '@disclosureos/records/shared';\nimport {\n ModalitySchema,\n TimeSourceSchema,\n CalibrationStatusSchema,\n UpgradeStatusSchema,\n} from '../manifest/types';\n\n// Enum guards are built from each schema's `.options` (a plain string tuple)\n// rather than the Zod schema itself: passing a Zod type across the package\n// boundary collides with Zod's internal version brand, whereas the literal\n// tuple is brand-free and still schema-derived.\nexport const isModality = createEnumGuard(ModalitySchema.options);\nexport const isTimeSource = createEnumGuard(TimeSourceSchema.options);\nexport const isCalibrationStatus = createEnumGuard(CalibrationStatusSchema.options);\nexport const isUpgradeStatus = createEnumGuard(UpgradeStatusSchema.options);\n","import { z } from 'zod';\nimport { jsonSchemaEnvelope, schemaId } from '@disclosureos/records/shared';\nimport { SensorManifestSchema } from './manifest/types';\n\n/**\n * Version of the emitted JSON Schema artifact. Bump on any intentional change\n * to the manifest shape; the committed `schema/sensor-manifest.schema.json` and\n * the drift test (`src/__tests__/schema.test.ts`) keep this honest.\n */\nexport const INSTRUMENTS_SCHEMA_VERSION = '1.0.0';\n\nexport const INSTRUMENTS_SCHEMA_ID = schemaId(\n 'instruments',\n 'sensor-manifest',\n INSTRUMENTS_SCHEMA_VERSION,\n);\n\n/**\n * Emit the canonical JSON Schema (draft 2020-12) for {@link SensorManifestSchema}.\n * Unlike the satellite slot schemas, this is a standalone document schema — a\n * manifest is published on its own, not composed into `Observation`.\n */\nexport function instrumentsJsonSchema(): Record<string, unknown> {\n const schema = z.toJSONSchema(SensorManifestSchema, { target: 'draft-2020-12' }) as Record<\n string,\n unknown\n >;\n return jsonSchemaEnvelope(schema, {\n id: INSTRUMENTS_SCHEMA_ID,\n version: INSTRUMENTS_SCHEMA_VERSION,\n });\n}\n","import type { Modality, SensorEntry, SensorManifest } from '../manifest/types';\nimport { INSTRUMENTS_SCHEMA_VERSION } from '../schema';\n\n/**\n * Build a sensor entry from the three required fields, with everything else\n * supplied via `options`.\n */\nexport function createSensorEntry(\n id: string,\n name: string,\n modality: Modality,\n options?: Partial<Omit<SensorEntry, 'id' | 'name' | 'modality'>>,\n): SensorEntry {\n return { id, name, modality, ...options };\n}\n\n/**\n * Build a sensor manifest. `schemaVersion` defaults to the version of the\n * schema this package emits.\n */\nexport function createSensorManifest(\n org: string,\n orgSlug: string,\n sensors: SensorEntry[],\n options?: Partial<Omit<SensorManifest, 'org' | 'orgSlug' | 'sensors'>>,\n): SensorManifest {\n return {\n schemaVersion: INSTRUMENTS_SCHEMA_VERSION,\n org,\n orgSlug,\n sensors,\n ...options,\n };\n}\n","import type { CalibrationStatus, Modality, SensorEntry, SensorManifest } from '../manifest/types';\nimport { MODALITY_LABELS, CALIBRATION_STATUS_LABELS } from '../labels';\n\nexport function formatModality(modality: Modality): string {\n return MODALITY_LABELS[modality];\n}\n\nexport function formatCalibrationStatus(status: CalibrationStatus): string {\n return CALIBRATION_STATUS_LABELS[status];\n}\n\n/** One-line sensor summary, e.g. `\"Passive Bistatic Radar (Radio Frequency) — calibration: In Practice\"`. */\nexport function formatSensorEntry(sensor: SensorEntry): string {\n const calibration = sensor.calibration\n ? ` — calibration: ${formatCalibrationStatus(sensor.calibration.status)}`\n : '';\n return `${sensor.name} (${formatModality(sensor.modality)})${calibration}`;\n}\n\n/** One-line manifest summary, e.g. `\"ELDÆON — 28 sensors across 6 modalities, 3 future upgrades\"`. */\nexport function formatSensorManifest(manifest: SensorManifest): string {\n const modalityCount = new Set(manifest.sensors.map((sensor) => sensor.modality)).size;\n const sensorCount = manifest.sensors.length;\n const upgrades = manifest.futureUpgrades?.length ?? 0;\n const upgradeSuffix = upgrades > 0 ? `, ${upgrades} future upgrade${upgrades === 1 ? '' : 's'}` : '';\n return `${manifest.org} — ${sensorCount} sensor${sensorCount === 1 ? '' : 's'} across ${modalityCount} modalit${modalityCount === 1 ? 'y' : 'ies'}${upgradeSuffix}`;\n}\n","import { validateWith } from '@disclosureos/records/shared';\nimport type { ValidationIssue } from '@disclosureos/records/shared';\nimport { SENSOR_TYPES, DETECTION_METHODS } from '@disclosureos/records/constants';\nimport { SensorManifestSchema } from '../manifest/types';\nimport type { SensorManifest } from '../manifest/types';\n\nconst KNOWN_SENSOR_TYPES = new Set<string>(SENSOR_TYPES);\nconst KNOWN_DETECTION_METHODS = new Set<string>(DETECTION_METHODS);\n\n/**\n * Validate a sensor manifest. Schema validation plus the structural invariants\n * Zod cannot express portably:\n *\n * 1. sensor ids are unique within the manifest;\n * 2. every `recordsMapping` value either exists in the `@disclosureos/records`\n * enums or carries the matching `proposed*` flag — so a manifest can never\n * silently claim a mapping the records vocabulary does not have.\n *\n * Returns a flat issue list (empty when valid) — the ecosystem's single\n * validation contract.\n */\nexport function validateSensorManifest(value: unknown): ValidationIssue[] {\n const issues = validateWith(SensorManifestSchema, value);\n if (issues.length > 0) return issues;\n\n const manifest = value as SensorManifest;\n const seenIds = new Set<string>();\n\n manifest.sensors.forEach((sensor, index) => {\n const path = `sensors.${index}`;\n\n if (seenIds.has(sensor.id)) {\n issues.push({ path: `${path}.id`, message: `Duplicate sensor id \"${sensor.id}\".` });\n }\n seenIds.add(sensor.id);\n\n const mapping = sensor.recordsMapping;\n if (!mapping) return;\n\n if (\n mapping.sensorType !== undefined\n && !KNOWN_SENSOR_TYPES.has(mapping.sensorType)\n && mapping.proposedSensorType !== true\n ) {\n issues.push({\n path: `${path}.recordsMapping.sensorType`,\n message:\n `\"${mapping.sensorType}\" is not a records SensorType; flag it with proposedSensorType: true or use a value from the enum.`,\n });\n }\n\n if (\n mapping.detectionMethod !== undefined\n && !KNOWN_DETECTION_METHODS.has(mapping.detectionMethod)\n && mapping.proposedDetectionMethod !== true\n ) {\n issues.push({\n path: `${path}.recordsMapping.detectionMethod`,\n message:\n `\"${mapping.detectionMethod}\" is not a records DetectionMethod; flag it with proposedDetectionMethod: true or use a value from the enum.`,\n });\n }\n });\n\n return issues;\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CalibrationStatus, Modality, TimeSource, UpgradeStatus } from '../manifest/index.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
declare const MODALITY_LABELS: Record<Modality, string>;
|
|
5
|
+
declare const TIME_SOURCE_LABELS: Record<TimeSource, string>;
|
|
6
|
+
declare const CALIBRATION_STATUS_LABELS: Record<CalibrationStatus, string>;
|
|
7
|
+
/** What each rung of the calibration maturity gradient means for a data consumer. */
|
|
8
|
+
declare const CALIBRATION_STATUS_DESCRIPTIONS: Record<CalibrationStatus, string>;
|
|
9
|
+
declare const UPGRADE_STATUS_LABELS: Record<UpgradeStatus, string>;
|
|
10
|
+
|
|
11
|
+
export { CALIBRATION_STATUS_DESCRIPTIONS, CALIBRATION_STATUS_LABELS, MODALITY_LABELS, TIME_SOURCE_LABELS, UPGRADE_STATUS_LABELS };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/labels/index.ts
|
|
2
|
+
var MODALITY_LABELS = {
|
|
3
|
+
audio: "Audio",
|
|
4
|
+
electro_optical: "Electro-Optical",
|
|
5
|
+
radio_frequency: "Radio Frequency",
|
|
6
|
+
quantum: "Quantum",
|
|
7
|
+
environmental: "Environmental",
|
|
8
|
+
biometric: "Biometric"
|
|
9
|
+
};
|
|
10
|
+
var TIME_SOURCE_LABELS = {
|
|
11
|
+
atomic_clock: "Atomic Clock",
|
|
12
|
+
gps_disciplined: "GPS-Disciplined",
|
|
13
|
+
ntp: "NTP",
|
|
14
|
+
system: "System Clock",
|
|
15
|
+
unknown: "Unknown"
|
|
16
|
+
};
|
|
17
|
+
var CALIBRATION_STATUS_LABELS = {
|
|
18
|
+
none: "None",
|
|
19
|
+
candidate_identified: "Candidate Identified",
|
|
20
|
+
in_practice: "In Practice",
|
|
21
|
+
documented: "Documented"
|
|
22
|
+
};
|
|
23
|
+
var CALIBRATION_STATUS_DESCRIPTIONS = {
|
|
24
|
+
none: "No calibration is performed. Declared honestly, this is itself useful information.",
|
|
25
|
+
candidate_identified: "A traceable reference has been named but is not yet part of practice.",
|
|
26
|
+
in_practice: "A real calibration method is performed today, but no full uncertainty budget exists.",
|
|
27
|
+
documented: "The calibration method and its uncertainty budget are published."
|
|
28
|
+
};
|
|
29
|
+
var UPGRADE_STATUS_LABELS = {
|
|
30
|
+
planned: "Planned",
|
|
31
|
+
evaluating: "Evaluating",
|
|
32
|
+
ordered: "Ordered",
|
|
33
|
+
acquired: "Acquired"
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { CALIBRATION_STATUS_DESCRIPTIONS, CALIBRATION_STATUS_LABELS, MODALITY_LABELS, TIME_SOURCE_LABELS, UPGRADE_STATUS_LABELS };
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/labels/index.ts"],"names":[],"mappings":";AAEO,IAAM,eAAA,GAA4C;AAAA,EACvD,KAAA,EAAO,OAAA;AAAA,EACP,eAAA,EAAiB,iBAAA;AAAA,EACjB,eAAA,EAAiB,iBAAA;AAAA,EACjB,OAAA,EAAS,SAAA;AAAA,EACT,aAAA,EAAe,eAAA;AAAA,EACf,SAAA,EAAW;AACb;AAEO,IAAM,kBAAA,GAAiD;AAAA,EAC5D,YAAA,EAAc,cAAA;AAAA,EACd,eAAA,EAAiB,iBAAA;AAAA,EACjB,GAAA,EAAK,KAAA;AAAA,EACL,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS;AACX;AAEO,IAAM,yBAAA,GAA+D;AAAA,EAC1E,IAAA,EAAM,MAAA;AAAA,EACN,oBAAA,EAAsB,sBAAA;AAAA,EACtB,WAAA,EAAa,aAAA;AAAA,EACb,UAAA,EAAY;AACd;AAGO,IAAM,+BAAA,GAAqE;AAAA,EAChF,IAAA,EAAM,oFAAA;AAAA,EACN,oBAAA,EAAsB,uEAAA;AAAA,EACtB,WAAA,EAAa,sFAAA;AAAA,EACb,UAAA,EAAY;AACd;AAEO,IAAM,qBAAA,GAAuD;AAAA,EAClE,OAAA,EAAS,SAAA;AAAA,EACT,UAAA,EAAY,YAAA;AAAA,EACZ,OAAA,EAAS,SAAA;AAAA,EACT,QAAA,EAAU;AACZ","file":"index.js","sourcesContent":["import type { Modality, TimeSource, CalibrationStatus, UpgradeStatus } from '../manifest/types';\n\nexport const MODALITY_LABELS: Record<Modality, string> = {\n audio: 'Audio',\n electro_optical: 'Electro-Optical',\n radio_frequency: 'Radio Frequency',\n quantum: 'Quantum',\n environmental: 'Environmental',\n biometric: 'Biometric',\n};\n\nexport const TIME_SOURCE_LABELS: Record<TimeSource, string> = {\n atomic_clock: 'Atomic Clock',\n gps_disciplined: 'GPS-Disciplined',\n ntp: 'NTP',\n system: 'System Clock',\n unknown: 'Unknown',\n};\n\nexport const CALIBRATION_STATUS_LABELS: Record<CalibrationStatus, string> = {\n none: 'None',\n candidate_identified: 'Candidate Identified',\n in_practice: 'In Practice',\n documented: 'Documented',\n};\n\n/** What each rung of the calibration maturity gradient means for a data consumer. */\nexport const CALIBRATION_STATUS_DESCRIPTIONS: Record<CalibrationStatus, string> = {\n none: 'No calibration is performed. Declared honestly, this is itself useful information.',\n candidate_identified: 'A traceable reference has been named but is not yet part of practice.',\n in_practice: 'A real calibration method is performed today, but no full uncertainty budget exists.',\n documented: 'The calibration method and its uncertainty budget are published.',\n};\n\nexport const UPGRADE_STATUS_LABELS: Record<UpgradeStatus, string> = {\n planned: 'Planned',\n evaluating: 'Evaluating',\n ordered: 'Ordered',\n acquired: 'Acquired',\n};\n"]}
|