@nextera.one/tps-standard 0.4.3 → 0.5.1

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/dist/index.d.ts CHANGED
@@ -2,9 +2,15 @@
2
2
  * TPS: Temporal Positioning System
3
3
  * The Universal Protocol for Space-Time Coordinates.
4
4
  * @packageDocumentation
5
- * @version 0.4.2
6
- * @license MIT
5
+ * @version 0.5.0
6
+ * @license Apache-2.0
7
7
  * @copyright 2026 TPS Standards Working Group
8
+ *
9
+ * v0.5.0 Changes:
10
+ * - Added Actor anchor (A:) for provenance tracking
11
+ * - Added Signature (!) for cryptographic verification
12
+ * - Added structural anchors (bldg, floor, room, zone)
13
+ * - Added geospatial cell systems (S2, H3, Plus Code, what3words)
8
14
  */
9
15
  export type CalendarCode = 'greg' | 'hij' | 'jul' | 'holo' | 'unix';
10
16
  export interface TPSComponents {
@@ -21,21 +27,91 @@ export interface TPSComponents {
21
27
  latitude?: number;
22
28
  longitude?: number;
23
29
  altitude?: number;
30
+ /** Google S2 cell ID (hierarchical, prefix-searchable) */
31
+ s2Cell?: string;
32
+ /** Uber H3 cell ID (hexagonal grid) */
33
+ h3Cell?: string;
34
+ /** Open Location Code / Plus Code */
35
+ plusCode?: string;
36
+ /** what3words address (e.g. "filled.count.soap") */
37
+ what3words?: string;
38
+ /** Physical building identifier */
39
+ building?: string;
40
+ /** Vertical division (level) */
41
+ floor?: string;
42
+ /** Enclosed space identifier */
43
+ room?: string;
44
+ /** Logical area within building */
45
+ zone?: string;
24
46
  /** Technical missing data (e.g. server log without GPS) */
25
47
  isUnknownLocation?: boolean;
26
48
  /** Removed for legal/security reasons (e.g. GDPR) */
27
49
  isRedactedLocation?: boolean;
28
50
  /** Masked by user preference (e.g. "Don't show my location") */
29
51
  isHiddenLocation?: boolean;
52
+ /** Actor anchor - identifies observer/witness (e.g. "did:web:sensor.example.com", "node:gateway-01") */
53
+ actor?: string;
54
+ /** Verification hash appended to time (e.g. "sha256:8f3e2a...") */
55
+ signature?: string;
30
56
  extensions?: Record<string, string>;
31
57
  }
32
58
  /**
33
59
  * Interface for Calendar Driver plugins.
34
- * Implementations must provide conversion logic to/from Gregorian.
60
+ * Implementations provide conversion logic to/from Gregorian and support for
61
+ * external calendar libraries.
62
+ *
63
+ * @example Using a driver to parse a Hijri date string
64
+ * ```ts
65
+ * const driver = TPS.getDriver('hij');
66
+ * if (driver?.parseDate) {
67
+ * const components = driver.parseDate('1447-07-21');
68
+ * const gregDate = driver.toGregorian(components);
69
+ * const tpsString = TPS.fromDate(gregDate, 'hij');
70
+ * }
71
+ * ```
72
+ *
73
+ * @example Wrapping an external library (moment-hijri)
74
+ * ```ts
75
+ * import moment from 'moment-hijri';
76
+ *
77
+ * class HijriDriver implements CalendarDriver {
78
+ * readonly code = 'hij';
79
+ *
80
+ * parseDate(input: string, format?: string): Partial<TPSComponents> {
81
+ * const m = moment(input, format || 'iYYYY-iMM-iDD');
82
+ * return {
83
+ * calendar: 'hij',
84
+ * year: m.iYear(),
85
+ * month: m.iMonth() + 1,
86
+ * day: m.iDate()
87
+ * };
88
+ * }
89
+ *
90
+ * fromGregorian(date: Date): Partial<TPSComponents> {
91
+ * const m = moment(date);
92
+ * return {
93
+ * calendar: 'hij',
94
+ * year: m.iYear(),
95
+ * month: m.iMonth() + 1,
96
+ * day: m.iDate(),
97
+ * hour: m.hour(),
98
+ * minute: m.minute(),
99
+ * second: m.second()
100
+ * };
101
+ * }
102
+ *
103
+ * // ... other methods
104
+ * }
105
+ * ```
35
106
  */
36
107
  export interface CalendarDriver {
37
108
  /** The calendar code this driver handles (e.g., 'hij', 'jul'). */
38
109
  readonly code: CalendarCode;
110
+ /**
111
+ * Human-readable name for this calendar (optional).
112
+ * @example "Hijri (Islamic)"
113
+ */
114
+ readonly name?: string;
39
115
  /**
40
116
  * Converts a Gregorian Date to this calendar's components.
41
117
  * @param date - The Gregorian Date object.
@@ -51,9 +127,87 @@ export interface CalendarDriver {
51
127
  /**
52
128
  * Generates a TPS time string for this calendar from a Date.
53
129
  * @param date - The Gregorian Date object.
54
- * @returns A TPS time string (e.g., "T:hij.m2.c5.y47...").
130
+ * @returns A TPS time string (e.g., "T:hij.y1447.M07.d21...").
55
131
  */
56
132
  fromDate(date: Date): string;
133
+ /**
134
+ * Parse a calendar-specific date string into TPS components.
135
+ * This allows drivers to handle native date formats from external libraries.
136
+ *
137
+ * @param input - Date string in calendar-native format (e.g., '1447-07-21' for Hijri)
138
+ * @param format - Optional format string (driver-specific, e.g., 'iYYYY-iMM-iDD')
139
+ * @returns Partial TPS components
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * // Hijri driver
144
+ * driver.parseDate('1447-07-21'); // → { year: 1447, month: 7, day: 21, calendar: 'hij' }
145
+ *
146
+ * // With time
147
+ * driver.parseDate('1447-07-21 14:30:00'); // → { year: 1447, month: 7, day: 21, hour: 14, ... }
148
+ * ```
149
+ */
150
+ parseDate?(input: string, format?: string): Partial<TPSComponents>;
151
+ /**
152
+ * Format TPS components to a calendar-specific date string.
153
+ * Inverse of parseDate().
154
+ *
155
+ * @param components - TPS components to format
156
+ * @param format - Optional format string (driver-specific)
157
+ * @returns Formatted date string in calendar-native format
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * driver.format({ year: 1447, month: 7, day: 21 }); // → '1447-07-21'
162
+ * driver.format({ year: 1447, month: 7, day: 21 }, 'short'); // → '21/7/1447'
163
+ * ```
164
+ */
165
+ format?(components: Partial<TPSComponents>, format?: string): string;
166
+ /**
167
+ * Validate a calendar-specific date string or components.
168
+ *
169
+ * @param input - Date string or components to validate
170
+ * @returns true if valid for this calendar
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * driver.validate('1447-13-01'); // → false (month 13 invalid)
175
+ * driver.validate({ year: 1447, month: 7, day: 31 }); // → false (Rajab has 30 days)
176
+ * ```
177
+ */
178
+ validate?(input: string | Partial<TPSComponents>): boolean;
179
+ /**
180
+ * Get calendar metadata (month names, day names, etc.).
181
+ * Useful for UI rendering.
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * driver.getMetadata().monthNames
186
+ * // → ['Muharram', 'Safar', 'Rabi I', ...]
187
+ * ```
188
+ */
189
+ getMetadata?(): CalendarMetadata;
190
+ }
191
+ /**
192
+ * Metadata about a calendar system.
193
+ */
194
+ export interface CalendarMetadata {
195
+ /** Human-readable calendar name */
196
+ name: string;
197
+ /** Month names in order (1-12 or 1-13) */
198
+ monthNames?: string[];
199
+ /** Short month names */
200
+ monthNamesShort?: string[];
201
+ /** Day of week names (Sunday=0 or locale-specific) */
202
+ dayNames?: string[];
203
+ /** Short day names */
204
+ dayNamesShort?: string[];
205
+ /** Whether this calendar is lunar-based */
206
+ isLunar?: boolean;
207
+ /** Number of months per year */
208
+ monthsPerYear?: number;
209
+ /** Epoch year (for reference) */
210
+ epochYear?: number;
57
211
  }
58
212
  export declare class TPS {
59
213
  private static readonly drivers;
@@ -101,6 +255,242 @@ export declare class TPS {
101
255
  * @returns JS Date object or `null` if invalid.
102
256
  */
103
257
  static toDate(tpsString: string): Date | null;
258
+ /**
259
+ * Parse a calendar-specific date string into TPS components.
260
+ * Requires the driver to implement the optional `parseDate` method.
261
+ *
262
+ * @param calendar - The calendar code (e.g., 'hij')
263
+ * @param dateString - Date string in calendar-native format (e.g., '1447-07-21')
264
+ * @param format - Optional format string (driver-specific)
265
+ * @returns TPS components or null if parsing fails
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * const components = TPS.parseCalendarDate('hij', '1447-07-21');
270
+ * // { calendar: 'hij', year: 1447, month: 7, day: 21 }
271
+ *
272
+ * const uri = TPS.toURI({ ...components, latitude: 31.95, longitude: 35.91 });
273
+ * // "tps://31.95,35.91@T:hij.y1447.M07.d21"
274
+ * ```
275
+ */
276
+ static parseCalendarDate(calendar: CalendarCode, dateString: string, format?: string): Partial<TPSComponents> | null;
277
+ /**
278
+ * Convert a calendar-specific date string directly to a TPS URI.
279
+ * This is a convenience method that combines parseDate + toURI.
280
+ *
281
+ * @param calendar - The calendar code (e.g., 'hij')
282
+ * @param dateString - Date string in calendar-native format
283
+ * @param location - Optional location (lat/lon/alt or privacy flag)
284
+ * @returns Full TPS URI string
285
+ *
286
+ * @example
287
+ * ```ts
288
+ * // With coordinates
289
+ * TPS.fromCalendarDate('hij', '1447-07-21', { latitude: 31.95, longitude: 35.91 });
290
+ * // "tps://31.95,35.91@T:hij.y1447.M07.d21"
291
+ *
292
+ * // With privacy flag
293
+ * TPS.fromCalendarDate('hij', '1447-07-21', { isHiddenLocation: true });
294
+ * // "tps://hidden@T:hij.y1447.M07.d21"
295
+ *
296
+ * // Without location
297
+ * TPS.fromCalendarDate('hij', '1447-07-21');
298
+ * // "tps://unknown@T:hij.y1447.M07.d21"
299
+ * ```
300
+ */
301
+ static fromCalendarDate(calendar: CalendarCode, dateString: string, location?: {
302
+ latitude?: number;
303
+ longitude?: number;
304
+ altitude?: number;
305
+ isUnknownLocation?: boolean;
306
+ isHiddenLocation?: boolean;
307
+ isRedactedLocation?: boolean;
308
+ }): string;
309
+ /**
310
+ * Format TPS components to a calendar-specific date string.
311
+ * Requires the driver to implement the optional `format` method.
312
+ *
313
+ * @param calendar - The calendar code
314
+ * @param components - TPS components to format
315
+ * @param format - Optional format string (driver-specific)
316
+ * @returns Formatted date string in calendar-native format
317
+ *
318
+ * @example
319
+ * ```ts
320
+ * const tps = TPS.parse('tps://unknown@T:hij.y1447.M07.d21');
321
+ * const formatted = TPS.formatCalendarDate('hij', tps);
322
+ * // "1447-07-21"
323
+ * ```
324
+ */
325
+ static formatCalendarDate(calendar: CalendarCode, components: Partial<TPSComponents>, format?: string): string;
104
326
  private static _mapGroupsToComponents;
105
327
  private static pad;
106
328
  }
329
+ /**
330
+ * Decoded result from TPSUID7RB binary format.
331
+ */
332
+ export type TPSUID7RBDecodeResult = {
333
+ /** Version identifier */
334
+ version: 'tpsuid7rb';
335
+ /** Epoch milliseconds (UTC) */
336
+ epochMs: number;
337
+ /** Whether the TPS payload was compressed */
338
+ compressed: boolean;
339
+ /** 32-bit nonce for collision prevention */
340
+ nonce: number;
341
+ /** The original TPS string (exact reconstruction) */
342
+ tps: string;
343
+ };
344
+ /**
345
+ * Encoding options for TPSUID7RB.
346
+ */
347
+ export type TPSUID7RBEncodeOptions = {
348
+ /** Enable zlib compression of TPS payload */
349
+ compress?: boolean;
350
+ /** Override epoch milliseconds (default: parsed from TPS) */
351
+ epochMs?: number;
352
+ };
353
+ /**
354
+ * TPS-UID v1 — Temporal Positioning System Identifier (Binary Reversible)
355
+ *
356
+ * A time-first, reversible identifier that binds an event to a TPS coordinate.
357
+ * Unlike UUIDs, TPS-UID identifies events in spacetime and allows exact
358
+ * reconstruction of the original TPS string.
359
+ *
360
+ * Binary Schema (all integers big-endian):
361
+ * ```
362
+ * MAGIC 4 bytes "TPU7"
363
+ * VER 1 byte 0x01
364
+ * FLAGS 1 byte bit0 = compression flag
365
+ * TIME 6 bytes epoch_ms (48-bit unsigned)
366
+ * NONCE 4 bytes 32-bit random
367
+ * LEN varint length of TPS payload
368
+ * TPS bytes UTF-8 TPS string (raw or zlib-compressed)
369
+ * ```
370
+ *
371
+ * @example
372
+ * ```ts
373
+ * const tps = 'tps://31.95,35.91@T:greg.m3.c1.y26.M01.d09';
374
+ *
375
+ * // Encode to binary
376
+ * const bytes = TPSUID7RB.encodeBinary(tps);
377
+ *
378
+ * // Encode to base64url string
379
+ * const id = TPSUID7RB.encodeBinaryB64(tps);
380
+ * // → "tpsuid7rb_AFRQV..."
381
+ *
382
+ * // Decode back to original TPS
383
+ * const decoded = TPSUID7RB.decodeBinaryB64(id);
384
+ * console.log(decoded.tps); // exact original TPS
385
+ * ```
386
+ */
387
+ export declare class TPSUID7RB {
388
+ /** Magic bytes: "TPU7" */
389
+ private static readonly MAGIC;
390
+ /** Version 1 */
391
+ private static readonly VER;
392
+ /** String prefix for base64url encoded form */
393
+ private static readonly PREFIX;
394
+ /** Regex for validating base64url encoded form */
395
+ static readonly REGEX: RegExp;
396
+ /**
397
+ * Encode TPS string to binary bytes (Uint8Array).
398
+ * This is the canonical form for hashing, signing, and storage.
399
+ *
400
+ * @param tps - The TPS string to encode
401
+ * @param opts - Encoding options (compress, epochMs override)
402
+ * @returns Binary TPS-UID as Uint8Array
403
+ */
404
+ static encodeBinary(tps: string, opts?: TPSUID7RBEncodeOptions): Uint8Array;
405
+ /**
406
+ * Decode binary bytes back to original TPS string.
407
+ *
408
+ * @param bytes - Binary TPS-UID
409
+ * @returns Decoded result with original TPS string
410
+ */
411
+ static decodeBinary(bytes: Uint8Array): TPSUID7RBDecodeResult;
412
+ /**
413
+ * Encode TPS to base64url string with prefix.
414
+ * This is the transport/storage form.
415
+ *
416
+ * @param tps - The TPS string to encode
417
+ * @param opts - Encoding options
418
+ * @returns Base64url encoded TPS-UID with prefix
419
+ */
420
+ static encodeBinaryB64(tps: string, opts?: TPSUID7RBEncodeOptions): string;
421
+ /**
422
+ * Decode base64url string back to original TPS string.
423
+ *
424
+ * @param id - Base64url encoded TPS-UID with prefix
425
+ * @returns Decoded result with original TPS string
426
+ */
427
+ static decodeBinaryB64(id: string): TPSUID7RBDecodeResult;
428
+ /**
429
+ * Validate base64url encoded TPS-UID format.
430
+ * Note: This validates shape only; binary decode is authoritative.
431
+ *
432
+ * @param id - String to validate
433
+ * @returns true if format is valid
434
+ */
435
+ static validateBinaryB64(id: string): boolean;
436
+ /**
437
+ * Generate a TPS-UID from the current time and optional location.
438
+ *
439
+ * @param opts - Generation options
440
+ * @returns Base64url encoded TPS-UID
441
+ */
442
+ static generate(opts?: {
443
+ latitude?: number;
444
+ longitude?: number;
445
+ altitude?: number;
446
+ compress?: boolean;
447
+ }): string;
448
+ /**
449
+ * Generate a TPS string from a Date and optional location.
450
+ */
451
+ private static generateTPSString;
452
+ /**
453
+ * Parse epoch milliseconds from a TPS string.
454
+ * Supports both URI format (tps://...) and time-only format (T:greg...)
455
+ */
456
+ static epochMsFromTPSString(tps: string): number;
457
+ /** Write 48-bit unsigned integer (big-endian) */
458
+ private static writeU48;
459
+ /** Read 48-bit unsigned integer (big-endian) */
460
+ private static readU48;
461
+ /** Encode unsigned integer as LEB128 varint */
462
+ private static uvarintEncode;
463
+ /** Decode LEB128 varint */
464
+ private static uvarintDecode;
465
+ /** Encode bytes to base64url (no padding) */
466
+ private static base64UrlEncode;
467
+ /** Decode base64url to bytes */
468
+ private static base64UrlDecode;
469
+ /** Compress using zlib deflate raw */
470
+ private static deflateRaw;
471
+ /** Decompress using zlib inflate raw */
472
+ private static inflateRaw;
473
+ /**
474
+ * Seal (sign) a TPS string to create a cryptographically verifiable TPS-UID.
475
+ * This appends an Ed25519 signature to the binary form.
476
+ *
477
+ * @param tps - The TPS string to seal
478
+ * @param privateKey - Ed25519 private key (hex or buffer)
479
+ * @param opts - Encoding options
480
+ * @returns Sealed binary TPS-UID
481
+ */
482
+ static seal(tps: string, privateKey: string | Buffer | Uint8Array, opts?: TPSUID7RBEncodeOptions): Uint8Array;
483
+ /**
484
+ * Verify a sealed TPS-UID and decode it.
485
+ * Throws if signature is invalid or not sealed.
486
+ *
487
+ * @param sealedBytes - The binary sealed TPS-UID
488
+ * @param publicKey - Ed25519 public key (hex or buffer) to verify against
489
+ * @returns Decoded result
490
+ */
491
+ static verifyAndDecode(sealedBytes: Uint8Array, publicKey: string | Buffer | Uint8Array): TPSUID7RBDecodeResult;
492
+ private static signEd25519;
493
+ private static verifyEd25519;
494
+ /** Generate cryptographically secure random bytes */
495
+ private static randomBytes;
496
+ }