@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/package.json ADDED
@@ -0,0 +1,103 @@
1
+ {
2
+ "name": "@disclosureos/instruments",
3
+ "version": "1.0.0",
4
+ "description": "UAP Sensor Manifest — per-sensor specification standard for detection hardware in the DisclosureOS ecosystem",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/disclosurefoundation/disclosureos"
9
+ },
10
+ "homepage": "https://github.com/disclosurefoundation/disclosureos#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/disclosurefoundation/disclosureos/issues"
13
+ },
14
+ "keywords": [
15
+ "disclosureos",
16
+ "UAP",
17
+ "instruments",
18
+ "sensors",
19
+ "sensor-manifest",
20
+ "calibration",
21
+ "provenance",
22
+ "typescript",
23
+ "research"
24
+ ],
25
+ "sideEffects": false,
26
+ "type": "module",
27
+ "engines": {
28
+ "node": ">=20.0.0"
29
+ },
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
34
+ },
35
+ "./manifest": {
36
+ "types": "./dist/manifest/index.d.ts",
37
+ "import": "./dist/manifest/index.js"
38
+ },
39
+ "./labels": {
40
+ "types": "./dist/labels/index.d.ts",
41
+ "import": "./dist/labels/index.js"
42
+ },
43
+ "./constants": {
44
+ "types": "./dist/constants/index.d.ts",
45
+ "import": "./dist/constants/index.js"
46
+ },
47
+ "./guards": {
48
+ "types": "./dist/guards/index.d.ts",
49
+ "import": "./dist/guards/index.js"
50
+ },
51
+ "./factories": {
52
+ "types": "./dist/factories/index.d.ts",
53
+ "import": "./dist/factories/index.js"
54
+ },
55
+ "./formatters": {
56
+ "types": "./dist/formatters/index.d.ts",
57
+ "import": "./dist/formatters/index.js"
58
+ },
59
+ "./validators": {
60
+ "types": "./dist/validators/index.d.ts",
61
+ "import": "./dist/validators/index.js"
62
+ },
63
+ "./schema": "./schema/sensor-manifest.schema.json",
64
+ "./package.json": "./package.json"
65
+ },
66
+ "main": "./dist/index.js",
67
+ "types": "./dist/index.d.ts",
68
+ "files": [
69
+ "dist",
70
+ "schema",
71
+ "README.md",
72
+ "CHANGELOG.md",
73
+ "LICENSE"
74
+ ],
75
+ "dependencies": {
76
+ "zod": "^4.4.3",
77
+ "@disclosureos/records": "1.1.0"
78
+ },
79
+ "devDependencies": {
80
+ "@types/node": "^20",
81
+ "tsup": "^8.0.0",
82
+ "tsx": "^4.21.0",
83
+ "typescript": "^5.7.2",
84
+ "vitest": "^4.0.18",
85
+ "@arethetypeswrong/cli": "^0.18.3",
86
+ "publint": "^0.3.21",
87
+ "@repo/typescript-config": "0.0.0"
88
+ },
89
+ "publishConfig": {
90
+ "access": "public"
91
+ },
92
+ "scripts": {
93
+ "build": "tsup",
94
+ "dev": "tsup --watch",
95
+ "lint": "eslint .",
96
+ "type-check": "tsc --noEmit",
97
+ "emit:schema": "tsx scripts/emit-schema.ts",
98
+ "clean": "rm -rf dist",
99
+ "test": "vitest",
100
+ "test:coverage": "vitest run --coverage",
101
+ "lint:publish": "publint --strict && attw --pack . --profile esm-only"
102
+ }
103
+ }
@@ -0,0 +1,473 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://os.disclosure.org/schema/instruments/1.0.0/sensor-manifest.json",
4
+ "x-schema-version": "1.0.0",
5
+ "description": "A published catalog of one organization’s 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.",
6
+ "$ref": "#/$defs/SensorManifest",
7
+ "$defs": {
8
+ "RecordsMapping": {
9
+ "type": "object",
10
+ "properties": {
11
+ "sensorType": {
12
+ "description": "The `@disclosureos/records` SensorType this sensor maps to.",
13
+ "type": "string"
14
+ },
15
+ "detectionMethod": {
16
+ "description": "The `@disclosureos/records` DetectionMethod this sensor maps to.",
17
+ "type": "string"
18
+ },
19
+ "proposedSensorType": {
20
+ "description": "True = sensorType is not in the records enum yet and is proposed by the publisher.",
21
+ "type": "boolean"
22
+ },
23
+ "proposedDetectionMethod": {
24
+ "description": "True = detectionMethod is not in the records enum yet and is proposed by the publisher.",
25
+ "type": "boolean"
26
+ }
27
+ },
28
+ "additionalProperties": false
29
+ },
30
+ "SensorTiming": {
31
+ "type": "object",
32
+ "properties": {
33
+ "timeSource": {
34
+ "type": "string",
35
+ "enum": [
36
+ "atomic_clock",
37
+ "gps_disciplined",
38
+ "ntp",
39
+ "system",
40
+ "unknown"
41
+ ],
42
+ "description": "Clock source that timestamps the sensor’s data."
43
+ },
44
+ "timeUncertaintyNs": {
45
+ "description": "Timestamp uncertainty in nanoseconds. Null = not yet characterized.",
46
+ "anyOf": [
47
+ {
48
+ "type": "number"
49
+ },
50
+ {
51
+ "type": "null"
52
+ }
53
+ ]
54
+ }
55
+ },
56
+ "required": [
57
+ "timeSource"
58
+ ],
59
+ "additionalProperties": false
60
+ },
61
+ "RawDataSpec": {
62
+ "type": "object",
63
+ "properties": {
64
+ "format": {
65
+ "description": "Raw-data file format, e.g. \"NDJSON.gz\", \"WAV\", \"MJPEG\", \"FITS\", \"CSV\".",
66
+ "type": "string"
67
+ },
68
+ "locatorPattern": {
69
+ "description": "Storage key pattern or path convention for locating the raw files.",
70
+ "anyOf": [
71
+ {
72
+ "type": "string"
73
+ },
74
+ {
75
+ "type": "null"
76
+ }
77
+ ]
78
+ },
79
+ "sampleRateHz": {
80
+ "description": "Sample rate in Hz, where applicable.",
81
+ "anyOf": [
82
+ {
83
+ "type": "number"
84
+ },
85
+ {
86
+ "type": "null"
87
+ }
88
+ ]
89
+ },
90
+ "bitDepth": {
91
+ "description": "Sample bit depth, where applicable.",
92
+ "anyOf": [
93
+ {
94
+ "type": "number"
95
+ },
96
+ {
97
+ "type": "null"
98
+ }
99
+ ]
100
+ }
101
+ },
102
+ "additionalProperties": false
103
+ },
104
+ "MeasurementUncertainty": {
105
+ "type": "object",
106
+ "properties": {
107
+ "u_c": {
108
+ "description": "Combined standard uncertainty.",
109
+ "anyOf": [
110
+ {
111
+ "type": "number"
112
+ },
113
+ {
114
+ "type": "null"
115
+ }
116
+ ]
117
+ },
118
+ "U": {
119
+ "description": "Expanded uncertainty (= k × u_c).",
120
+ "anyOf": [
121
+ {
122
+ "type": "number"
123
+ },
124
+ {
125
+ "type": "null"
126
+ }
127
+ ]
128
+ },
129
+ "k": {
130
+ "description": "Coverage factor (2 ≈ 95% confidence level).",
131
+ "anyOf": [
132
+ {
133
+ "type": "number"
134
+ },
135
+ {
136
+ "type": "null"
137
+ }
138
+ ]
139
+ },
140
+ "type": {
141
+ "anyOf": [
142
+ {
143
+ "type": "string",
144
+ "enum": [
145
+ "A",
146
+ "B"
147
+ ],
148
+ "description": "GUM uncertainty evaluation type: A (statistical) or B (other means)."
149
+ },
150
+ {
151
+ "type": "null"
152
+ }
153
+ ]
154
+ }
155
+ },
156
+ "additionalProperties": false
157
+ },
158
+ "Measurement": {
159
+ "type": "object",
160
+ "properties": {
161
+ "name": {
162
+ "type": "string",
163
+ "minLength": 1,
164
+ "description": "Measured quantity, e.g. \"differential_pressure\"."
165
+ },
166
+ "unit": {
167
+ "type": "string",
168
+ "minLength": 1,
169
+ "description": "UCUM-style unit string, e.g. \"Pa\", \"dB\", \"uT\", \"ppm\", \"/min\"."
170
+ },
171
+ "uncertainty": {
172
+ "description": "GUM-style measurement uncertainty. Fields are nullable until an uncertainty budget exists — declaring \"unknown\" honestly is itself information.",
173
+ "$ref": "#/$defs/MeasurementUncertainty"
174
+ }
175
+ },
176
+ "required": [
177
+ "name",
178
+ "unit"
179
+ ],
180
+ "additionalProperties": false
181
+ },
182
+ "SensorCalibration": {
183
+ "type": "object",
184
+ "properties": {
185
+ "status": {
186
+ "type": "string",
187
+ "enum": [
188
+ "none",
189
+ "candidate_identified",
190
+ "in_practice",
191
+ "documented"
192
+ ],
193
+ "description": "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."
194
+ },
195
+ "calibrated": {
196
+ "description": "Coarse calibrated flag, mirroring `SensorReading.calibrated`. Null = undetermined.",
197
+ "anyOf": [
198
+ {
199
+ "type": "boolean"
200
+ },
201
+ {
202
+ "type": "null"
203
+ }
204
+ ]
205
+ },
206
+ "currentMethod": {
207
+ "description": "What the operator actually does today. Null = no calibration currently performed.",
208
+ "anyOf": [
209
+ {
210
+ "type": "string"
211
+ },
212
+ {
213
+ "type": "null"
214
+ }
215
+ ]
216
+ },
217
+ "traceableReference": {
218
+ "description": "Traceable reference, in use or identified as a candidate (e.g. \"GPS/UTC\", \"USGS/INTERMAGNET\").",
219
+ "anyOf": [
220
+ {
221
+ "type": "string"
222
+ },
223
+ {
224
+ "type": "null"
225
+ }
226
+ ]
227
+ },
228
+ "referenceInUse": {
229
+ "description": "True = the traceable reference is part of current practice. False = identified candidate only. Null = undetermined.",
230
+ "anyOf": [
231
+ {
232
+ "type": "boolean"
233
+ },
234
+ {
235
+ "type": "null"
236
+ }
237
+ ]
238
+ },
239
+ "cadence": {
240
+ "description": "How often calibration is performed.",
241
+ "anyOf": [
242
+ {
243
+ "type": "string"
244
+ },
245
+ {
246
+ "type": "null"
247
+ }
248
+ ]
249
+ },
250
+ "uncertaintyBudget": {
251
+ "description": "Published uncertainty budget, if any.",
252
+ "anyOf": [
253
+ {
254
+ "type": "string"
255
+ },
256
+ {
257
+ "type": "null"
258
+ }
259
+ ]
260
+ },
261
+ "notes": {
262
+ "description": "Open questions or method caveats.",
263
+ "anyOf": [
264
+ {
265
+ "type": "string"
266
+ },
267
+ {
268
+ "type": "null"
269
+ }
270
+ ]
271
+ }
272
+ },
273
+ "required": [
274
+ "status"
275
+ ],
276
+ "additionalProperties": false
277
+ },
278
+ "SensorEntry": {
279
+ "type": "object",
280
+ "properties": {
281
+ "id": {
282
+ "type": "string",
283
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
284
+ "description": "Stable kebab-case id, unique within the manifest; addressable from a record via `SensorReading.sensorRef` (\"<org-slug>:<sensor-id>\")."
285
+ },
286
+ "name": {
287
+ "type": "string",
288
+ "minLength": 1,
289
+ "description": "Human-readable sensor name."
290
+ },
291
+ "modality": {
292
+ "type": "string",
293
+ "enum": [
294
+ "audio",
295
+ "electro_optical",
296
+ "radio_frequency",
297
+ "quantum",
298
+ "environmental",
299
+ "biometric"
300
+ ],
301
+ "description": "Top-level sensing modality the sensor belongs to."
302
+ },
303
+ "manufacturerModel": {
304
+ "description": "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).",
305
+ "type": "string"
306
+ },
307
+ "inHouse": {
308
+ "description": "True if operator-built rather than off-the-shelf.",
309
+ "type": "boolean"
310
+ },
311
+ "compute": {
312
+ "description": "The compute unit this sensor is attached to, for platforms with several compute nodes.",
313
+ "type": "string"
314
+ },
315
+ "recordsMapping": {
316
+ "description": "How this sensor maps to the `SensorReading` vocabulary in `@disclosureos/records`. Values outside the records enums must carry the matching proposed* flag.",
317
+ "$ref": "#/$defs/RecordsMapping"
318
+ },
319
+ "timing": {
320
+ "description": "Timing provenance. Timestamp error of even a few seconds confounds multi-station correlation, so the clock source must be declared, not assumed.",
321
+ "$ref": "#/$defs/SensorTiming"
322
+ },
323
+ "rawData": {
324
+ "description": "Raw-data format and locator. Supports a metadata-first architecture: circulate manifests widely, pull raw data on demand.",
325
+ "$ref": "#/$defs/RawDataSpec"
326
+ },
327
+ "measurements": {
328
+ "type": "array",
329
+ "items": {
330
+ "description": "One measured quantity with its unit and uncertainty.",
331
+ "$ref": "#/$defs/Measurement"
332
+ }
333
+ },
334
+ "calibration": {
335
+ "description": "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.",
336
+ "$ref": "#/$defs/SensorCalibration"
337
+ },
338
+ "specs": {
339
+ "description": "Free-form hardware specifications from the operator’s spec sheet (resolution, range, sensitivity, interface, …). Keys vary by modality.",
340
+ "type": "object",
341
+ "propertyNames": {
342
+ "type": "string"
343
+ },
344
+ "additionalProperties": {}
345
+ },
346
+ "specSource": {
347
+ "description": "Provenance of the spec values.",
348
+ "type": "string"
349
+ }
350
+ },
351
+ "required": [
352
+ "id",
353
+ "name",
354
+ "modality"
355
+ ],
356
+ "additionalProperties": false
357
+ },
358
+ "FutureUpgrade": {
359
+ "type": "object",
360
+ "properties": {
361
+ "name": {
362
+ "type": "string",
363
+ "minLength": 1
364
+ },
365
+ "modality": {
366
+ "type": "string",
367
+ "enum": [
368
+ "audio",
369
+ "electro_optical",
370
+ "radio_frequency",
371
+ "quantum",
372
+ "environmental",
373
+ "biometric"
374
+ ],
375
+ "description": "Top-level sensing modality the sensor belongs to."
376
+ },
377
+ "status": {
378
+ "type": "string",
379
+ "enum": [
380
+ "planned",
381
+ "evaluating",
382
+ "ordered",
383
+ "acquired"
384
+ ],
385
+ "description": "Acquisition status of a declared future hardware upgrade."
386
+ },
387
+ "specs": {
388
+ "type": "object",
389
+ "propertyNames": {
390
+ "type": "string"
391
+ },
392
+ "additionalProperties": {}
393
+ },
394
+ "link": {
395
+ "description": "Public product or reference page, where the publisher chooses to share one.",
396
+ "anyOf": [
397
+ {
398
+ "type": "string"
399
+ },
400
+ {
401
+ "type": "null"
402
+ }
403
+ ]
404
+ },
405
+ "notes": {
406
+ "anyOf": [
407
+ {
408
+ "type": "string"
409
+ },
410
+ {
411
+ "type": "null"
412
+ }
413
+ ]
414
+ }
415
+ },
416
+ "required": [
417
+ "name",
418
+ "modality"
419
+ ],
420
+ "additionalProperties": false
421
+ },
422
+ "SensorManifest": {
423
+ "type": "object",
424
+ "properties": {
425
+ "schemaVersion": {
426
+ "type": "string",
427
+ "minLength": 1,
428
+ "description": "Version of the sensor-manifest schema this instance targets (SemVer)."
429
+ },
430
+ "org": {
431
+ "type": "string",
432
+ "minLength": 1,
433
+ "description": "Publishing organization, display form (e.g. \"ELDÆON\")."
434
+ },
435
+ "orgSlug": {
436
+ "type": "string",
437
+ "pattern": "^[a-z0-9][a-z0-9-]*$",
438
+ "description": "Stable lowercase slug for the publisher (e.g. \"eldaeon\"); the org half of a `sensorRef`."
439
+ },
440
+ "orgUrl": {
441
+ "description": "URL for the publishing organization.",
442
+ "type": "string"
443
+ },
444
+ "generatedAt": {
445
+ "description": "ISO date the manifest was generated.",
446
+ "type": "string"
447
+ },
448
+ "sensors": {
449
+ "minItems": 1,
450
+ "type": "array",
451
+ "items": {
452
+ "description": "One sensor: its class, spec, timing, raw-data locator, measurements, and calibration provenance.",
453
+ "$ref": "#/$defs/SensorEntry"
454
+ }
455
+ },
456
+ "futureUpgrades": {
457
+ "type": "array",
458
+ "items": {
459
+ "description": "Planned hardware declared ahead of deployment so data consumers can anticipate new streams. Not part of the live sensor array.",
460
+ "$ref": "#/$defs/FutureUpgrade"
461
+ }
462
+ }
463
+ },
464
+ "required": [
465
+ "schemaVersion",
466
+ "org",
467
+ "orgSlug",
468
+ "sensors"
469
+ ],
470
+ "additionalProperties": false
471
+ }
472
+ }
473
+ }