@oxyhq/core 3.11.0 → 3.12.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.
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.SignatureService = void 0;
10
10
  exports.signedRecordSigningInput = signedRecordSigningInput;
11
+ exports.computeRecordId = computeRecordId;
11
12
  const elliptic_1 = require("elliptic");
12
13
  const keyManager_1 = require("./keyManager");
13
14
  const canonicalJson_1 = require("./canonicalJson");
@@ -19,15 +20,42 @@ const ec = new elliptic_1.ec('secp256k1');
19
20
  /**
20
21
  * Compute the canonical signing input for a signed-record envelope.
21
22
  *
22
- * This is the single definition of "what the signature covers": the canonical
23
- * JSON of `{version, type, subject, issuer, record, issuedAt}`. `@oxyhq/core`
23
+ * This is the single definition of "what the signature covers". `@oxyhq/core`
24
24
  * (client signing) and `@oxyhq/api` (server verification) both call this, so a
25
25
  * record signed by a client and verified by the server cannot drift.
26
+ *
27
+ * - **v1**: the canonical JSON of `{version, type, subject, issuer, record,
28
+ * issuedAt}` — BYTE-IDENTICAL to the original scheme, so every signature
29
+ * already in production keeps verifying.
30
+ * - **v2**: the canonical JSON additionally includes the hash-chain fields
31
+ * `{seq, prev, collection, rkey}`. Because {@link canonicalize} sorts keys,
32
+ * the on-the-wire field order is irrelevant; the resulting canonical key
33
+ * order is `collection, issuedAt, issuer, prev, record, rkey, seq, subject,
34
+ * type, version`. `prev` is `null` at genesis (serialized as `null`, not
35
+ * omitted), so it is always part of the signed bytes.
26
36
  */
27
37
  function signedRecordSigningInput(fields) {
28
38
  const { version, type, subject, issuer, record, issuedAt } = fields;
39
+ if (version === 2) {
40
+ const { seq, prev, collection, rkey } = fields;
41
+ return (0, canonicalJson_1.canonicalize)({ version, type, subject, issuer, record, issuedAt, seq, prev, collection, rkey });
42
+ }
29
43
  return (0, canonicalJson_1.canonicalize)({ version, type, subject, issuer, record, issuedAt });
30
44
  }
45
+ /**
46
+ * Compute the `recordId` (content address) of a signed record: the SHA-256 hex
47
+ * digest of its canonical {@link signedRecordSigningInput}.
48
+ *
49
+ * Deterministic and stable across runtimes (it reuses the same canonicalization
50
+ * + SHA-256 the signature itself is built on). The recordId is what `prev`
51
+ * references in the per-subject hash chain, so `@oxyhq/core` (client) and
52
+ * `@oxyhq/api` (server) MUST compute it identically — both call this function.
53
+ * It is taken over the SIGNING input (excluding `publicKey`/`signature`), so it
54
+ * is a pure content address of the record's meaning, independent of who signed.
55
+ */
56
+ async function computeRecordId(fields) {
57
+ return sha256(signedRecordSigningInput(fields));
58
+ }
31
59
  /**
32
60
  * Compute SHA-256 hash of a string
33
61
  */
@@ -343,6 +371,64 @@ class SignatureService {
343
371
  signature,
344
372
  };
345
373
  }
374
+ /**
375
+ * Build a signed-record envelope (v2) carrying the per-subject hash-chain
376
+ * fields.
377
+ *
378
+ * Identical to {@link signRecord} (self-issued: `issuer === subject`; same
379
+ * `ES256K-DER-SHA256` scheme over {@link signedRecordSigningInput}) but
380
+ * `version` is `2` and the signed bytes additionally cover the chain fields:
381
+ *
382
+ * @param type - The record category.
383
+ * @param subject - The subject DID the record is about (also the issuer).
384
+ * @param record - The arbitrary record payload to attest to.
385
+ * @param chain - The hash-chain coordinates:
386
+ * - `seq` — strictly-increasing sequence number for this subject's chain.
387
+ * - `prev` — the `recordId` of the previous record, or `null` at genesis.
388
+ * - `collection` + `rkey` — the AtProto-style record key.
389
+ *
390
+ * The caller is responsible for fetching the current chain head (so `seq` /
391
+ * `prev` are correct) before signing. Requires a stored identity; throws if
392
+ * none exists.
393
+ */
394
+ static async signRecordV2(type, subject, record, chain) {
395
+ const publicKey = await keyManager_1.KeyManager.getPublicKey();
396
+ if (!publicKey) {
397
+ throw new Error('No identity found. Please create or import an identity first.');
398
+ }
399
+ const version = 2;
400
+ const issuer = subject;
401
+ const issuedAt = Date.now();
402
+ const { seq, prev, collection, rkey } = chain;
403
+ const signingInput = signedRecordSigningInput({
404
+ version,
405
+ type,
406
+ subject,
407
+ issuer,
408
+ record,
409
+ issuedAt,
410
+ seq,
411
+ prev,
412
+ collection,
413
+ rkey,
414
+ });
415
+ const signature = await SignatureService.sign(signingInput);
416
+ return {
417
+ version,
418
+ type,
419
+ subject,
420
+ issuer,
421
+ record,
422
+ issuedAt,
423
+ seq,
424
+ prev,
425
+ collection,
426
+ rkey,
427
+ publicKey,
428
+ alg: 'ES256K-DER-SHA256',
429
+ signature,
430
+ };
431
+ }
346
432
  /**
347
433
  * Verify a signed-record envelope: recompute the canonical signing input from
348
434
  * the envelope's own fields and check the signature against the envelope's
package/dist/cjs/index.js CHANGED
@@ -18,10 +18,10 @@
18
18
  * If a symbol does not appear here, it is NOT part of the public API.
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.darkenColor = exports.isAndroid = exports.isIOS = exports.isNative = exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.isRTLLocale = exports.normalizeLanguageCode = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.RecoveryPhraseService = exports.canonicalize = exports.signedRecordSigningInput = exports.SignatureService = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = exports.sessionsArraysEqual = exports.normalizeAndSortSessions = exports.mergeSessions = exports.authenticatedApiCall = exports.withAuthErrorHandling = exports.isAuthenticationError = exports.ensureValidToken = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.buildUserDid = exports.getNormalizedUserHandle = exports.getCanonicalUserHandle = exports.normalizeUserIdentityOrNull = exports.normalizeUserIdentity = exports.getNormalizedUserId = exports.OxyAppDataIdentifierError = exports.ServiceCredentialMismatchError = exports.createCrossDomainAuth = exports.CrossDomainAuth = exports.createAuthManager = exports.AuthManager = exports.oxyClient = exports.OXY_CLOUD_URL = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.OxyServices = void 0;
22
- exports.isValidUsername = exports.isValidEmail = exports.PASSWORD_REGEX = exports.USERNAME_REGEX = exports.EMAIL_REGEX = exports.retryAsync = exports.validateRequiredFields = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.translate = exports.createDebugLogger = exports.debugError = exports.debugWarn = exports.debugLog = exports.isDev = exports.withRetry = exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = void 0;
23
- exports.getSsoCallbackBootstrapScript = exports.ssoNavigate = exports.ssoCallbackBootstrapKey = exports.ssoAttemptedKey = exports.ssoNoSessionKey = exports.ssoDestKey = exports.ssoGuardKey = exports.ssoStateKey = exports.SSO_GUARD_TTL_MS = exports.SSO_CALLBACK_PATH = exports.generateSsoState = exports.consumeSsoReturn = exports.parseSsoReturnFragment = exports.resolveCentralAuthUrl = exports.CENTRAL_IDP_APEX = exports.CENTRAL_AUTH_URL = exports.registrableApex = exports.autoDetectAuthWebUrl = exports.getAccountColor = exports.mergeAccountsFromRefreshAll = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.logPerformance = exports.logPayment = exports.logDevice = exports.logUser = exports.logSession = exports.logApi = exports.logAuth = exports.LogLevel = exports.logger = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.isValidPassword = void 0;
24
- exports.packageInfo = exports.runColdBoot = exports.guardActive = exports.isCentralIdPOrigin = exports.buildSsoBounceUrl = void 0;
21
+ exports.setPlatformOS = exports.getPlatformOS = exports.isRTLLocale = exports.normalizeLanguageCode = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.RecoveryPhraseService = exports.canonicalize = exports.computeRecordId = exports.signedRecordSigningInput = exports.SignatureService = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = exports.sessionsArraysEqual = exports.normalizeAndSortSessions = exports.mergeSessions = exports.authenticatedApiCall = exports.withAuthErrorHandling = exports.isAuthenticationError = exports.ensureValidToken = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.verifyPublicCardAttestation = exports.parseAttestPayload = exports.parseIdPayload = exports.buildUserDid = exports.normalizeProfileLinks = exports.getNormalizedUserHandle = exports.getCanonicalUserHandle = exports.normalizeUserIdentityOrNull = exports.normalizeUserIdentity = exports.getNormalizedUserId = exports.OxyAppDataIdentifierError = exports.ServiceCredentialMismatchError = exports.createCrossDomainAuth = exports.CrossDomainAuth = exports.createAuthManager = exports.AuthManager = exports.oxyClient = exports.OXY_CLOUD_URL = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.OxyServices = void 0;
22
+ exports.retryAsync = exports.validateRequiredFields = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.translate = exports.createDebugLogger = exports.debugError = exports.debugWarn = exports.debugLog = exports.isDev = exports.withRetry = exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = exports.darkenColor = exports.isAndroid = exports.isIOS = exports.isNative = exports.isWeb = void 0;
23
+ exports.ssoDestKey = exports.ssoGuardKey = exports.ssoStateKey = exports.SSO_GUARD_TTL_MS = exports.SSO_CALLBACK_PATH = exports.generateSsoState = exports.consumeSsoReturn = exports.parseSsoReturnFragment = exports.resolveCentralAuthUrl = exports.CENTRAL_IDP_APEX = exports.CENTRAL_AUTH_URL = exports.registrableApex = exports.autoDetectAuthWebUrl = exports.getAccountColor = exports.mergeAccountsFromRefreshAll = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.logPerformance = exports.logPayment = exports.logDevice = exports.logUser = exports.logSession = exports.logApi = exports.logAuth = exports.LogLevel = exports.logger = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.isValidPassword = exports.isValidUsername = exports.isValidEmail = exports.PASSWORD_REGEX = exports.USERNAME_REGEX = exports.EMAIL_REGEX = void 0;
24
+ exports.packageInfo = exports.runColdBoot = exports.guardActive = exports.isCentralIdPOrigin = exports.buildSsoBounceUrl = exports.getSsoCallbackBootstrapScript = exports.ssoNavigate = exports.ssoCallbackBootstrapKey = exports.ssoAttemptedKey = exports.ssoNoSessionKey = void 0;
25
25
  // Ensure crypto polyfills are loaded before anything else
26
26
  require("./crypto/polyfill");
27
27
  // ---------------------------------------------------------------------------
@@ -57,6 +57,8 @@ Object.defineProperty(exports, "normalizeUserIdentityOrNull", { enumerable: true
57
57
  var userHandle_1 = require("./utils/userHandle");
58
58
  Object.defineProperty(exports, "getCanonicalUserHandle", { enumerable: true, get: function () { return userHandle_1.getCanonicalUserHandle; } });
59
59
  Object.defineProperty(exports, "getNormalizedUserHandle", { enumerable: true, get: function () { return userHandle_1.getNormalizedUserHandle; } });
60
+ var profileLinks_1 = require("./utils/profileLinks");
61
+ Object.defineProperty(exports, "normalizeProfileLinks", { enumerable: true, get: function () { return profileLinks_1.normalizeProfileLinks; } });
60
62
  // ---------------------------------------------------------------------------
61
63
  // Self-sovereign identity (DID, signed records, auth-method ↔ VM mapping,
62
64
  // verified domains). Wire shapes (DidDocument, SignedRecordEnvelope,
@@ -66,6 +68,18 @@ Object.defineProperty(exports, "getNormalizedUserHandle", { enumerable: true, ge
66
68
  var OxyServices_identity_1 = require("./mixins/OxyServices.identity");
67
69
  Object.defineProperty(exports, "buildUserDid", { enumerable: true, get: function () { return OxyServices_identity_1.buildUserDid; } });
68
70
  // ---------------------------------------------------------------------------
71
+ // Civic / Commons "Oxy ID" (public signed cards + Oxy ID QR payload) and Fase 2
72
+ // anti-gaming (real-life attestation QR + validator/jury). Wire shapes
73
+ // (PublicCard, SignedPublicCard, RealLifeAttestationResult,
74
+ // ValidationRequestSummary, ValidationVoteResult, ValidationVerdict, …) live in
75
+ // `@oxyhq/contracts` — import them from there. The SDK adds the client verdict
76
+ // wrapper, the QR payload parsers/builders, and the submit inputs/results.
77
+ // ---------------------------------------------------------------------------
78
+ var OxyServices_civic_1 = require("./mixins/OxyServices.civic");
79
+ Object.defineProperty(exports, "parseIdPayload", { enumerable: true, get: function () { return OxyServices_civic_1.parseIdPayload; } });
80
+ Object.defineProperty(exports, "parseAttestPayload", { enumerable: true, get: function () { return OxyServices_civic_1.parseAttestPayload; } });
81
+ Object.defineProperty(exports, "verifyPublicCardAttestation", { enumerable: true, get: function () { return OxyServices_civic_1.verifyPublicCardAttestation; } });
82
+ // ---------------------------------------------------------------------------
69
83
  // Auth helpers (token refresh, error normalisation, retry policies)
70
84
  // ---------------------------------------------------------------------------
71
85
  var authHelpers_1 = require("./utils/authHelpers");
@@ -92,6 +106,7 @@ Object.defineProperty(exports, "IdentityPersistError", { enumerable: true, get:
92
106
  var signatureService_1 = require("./crypto/signatureService");
93
107
  Object.defineProperty(exports, "SignatureService", { enumerable: true, get: function () { return signatureService_1.SignatureService; } });
94
108
  Object.defineProperty(exports, "signedRecordSigningInput", { enumerable: true, get: function () { return signatureService_1.signedRecordSigningInput; } });
109
+ Object.defineProperty(exports, "computeRecordId", { enumerable: true, get: function () { return signatureService_1.computeRecordId; } });
95
110
  var canonicalJson_1 = require("./crypto/canonicalJson");
96
111
  Object.defineProperty(exports, "canonicalize", { enumerable: true, get: function () { return canonicalJson_1.canonicalize; } });
97
112
  var recoveryPhrase_1 = require("./crypto/recoveryPhrase");