@opendatalabs/vana-sdk 3.21.0 → 3.22.0-pr.207.0dbb052

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/README.md CHANGED
@@ -621,6 +621,70 @@ These helpers require `personal-server-ts` main `d91124d` or later, which is
621
621
  where the query-in-the-signed-uri rule, the `nonce` claim, the 404 for an
622
622
  unknown id and the full-view `recompute` answer landed.
623
623
 
624
+ ### Watching a derived scope as the reader
625
+
626
+ The helpers above are the builder's: every one of them needs a write session,
627
+ which an app holding only a bare read entry on the derived scope cannot open.
628
+ That reader sees `GET /v1/data/<derivedScope>` answer 404 whether the compute
629
+ is running, retrying, or finished failing.
630
+
631
+ `getDerivativeStatus` is the reader's view of the same question. It
632
+ authenticates like a data read — a live grant covering the derived scope, or
633
+ the owner — and nothing is charged, so a priced grant raises no 402 here.
634
+
635
+ ```typescript
636
+ import {
637
+ getDerivativeStatus,
638
+ waitForDerivativeStatus,
639
+ } from "@opendatalabs/vana-sdk";
640
+
641
+ const status = await getDerivativeStatus({
642
+ personalServerUrl: "https://ps.example.com",
643
+ derivedScope: "coach.weekly",
644
+ grantId,
645
+ signer,
646
+ });
647
+ // { derivedScope, status, lastComputedAt, derivedVersion,
648
+ // derivedCollectedAt, errorCode, retryAfterSeconds }
649
+
650
+ const settled = await waitForDerivativeStatus({
651
+ personalServerUrl: "https://ps.example.com",
652
+ derivedScope: "coach.weekly",
653
+ grantId,
654
+ signer,
655
+ timeoutMs: 60_000,
656
+ });
657
+ ```
658
+
659
+ The view is lifecycle only: the question text, the source scopes, the question
660
+ id, the registrar and the server's raw `error` string stay owner-only.
661
+ `errorCode` is a closed vocabulary — `inference_unavailable`,
662
+ `source_missing`, `grant_invalid`, `internal` — and is `null` unless `status`
663
+ is `failed`.
664
+
665
+ `retryAfterSeconds` is what separates a failure that is still being worked on
666
+ from one that is over: `inference_unavailable` is the one transient class, and
667
+ the Personal Server retries it on its own schedule. `waitForDerivativeStatus`
668
+ returns as soon as the scope is `ready` or has failed with no retry pending,
669
+ keeps waiting through a retrying failure, and takes the server's
670
+ `retryAfterSeconds` as the cadence in place of `pollIntervalMs`, longer or
671
+ shorter — it is when the next compute actually happens, so asking sooner sees
672
+ nothing new and asking later sits on an answer that already exists. Once the
673
+ remaining budget cannot cover the next cadence it raises the timeout rather
674
+ than spending one more request that cannot carry new data. `signal` aborts
675
+ the wait and the request in flight with it. A failed status is returned, not thrown; branch
676
+ on `errorCode`. `isDerivativeStatusSettled` is the same predicate, exported
677
+ for callers that poll on their own.
678
+
679
+ When several questions write the same derived scope, the most optimistic true
680
+ state answers (`ready`, then `stale`, then `pending`, then `failed`), because
681
+ serving data is registration-agnostic: a duplicate that never wrote anything
682
+ must not report away an answer the scope has.
683
+
684
+ The status route needs a Personal Server that ships it; an older one answers
685
+ 404 for the route itself, which arrives as `DerivativeQuestionNotFoundError`
686
+ — the same error as a covered scope with no question behind it.
687
+
624
688
  ## Networks
625
689
 
626
690
  | Network | Chain ID | RPC URL |
@@ -37,6 +37,7 @@ export { parseWeb3SignedHeader, verifyWeb3Signed, type Web3SignedPayload, type V
37
37
  export { buildWeb3SignedHeader, computeBodyHash, type Web3SignedSignFn, } from "./auth/web3-signed-builder.js";
38
38
  export { MissingAuthError, InvalidSignatureError, ExpiredTokenError, } from "./auth/errors.js";
39
39
  export { NATIVE_VANA_ASSET, dataRegistryDomain, grantRegistrationDomain, grantRevocationDomain, serverRegistrationDomain, builderRegistrationDomain, escrowPaymentDomain, GRANT_REGISTRATION_TYPES, GRANT_REVOCATION_TYPES, SERVER_REGISTRATION_TYPES, BUILDER_REGISTRATION_TYPES, ADD_DATA_TYPES, RECORD_DATA_ACCESS_TYPES, type DataPortabilityContracts, type DataPortabilityGatewayConfig, type GrantRegistrationMessage, type GrantRevocationMessage, type ServerRegistrationMessage, type BuilderRegistrationMessage, type AddDataMessage, type RecordDataAccessMessage, } from "./protocol/eip712.js";
40
+ export { ENCLAVE_IDENTITY_EVIDENCE_VERSION, USER_PS_ID_DOMAIN, ENCLAVE_WALLET_PURPOSE, MASTER_SIGNATURE_DELIVERY_VERSION, SEALED_ENVELOPE_VERSION, ENCLAVE_TRUST_ANCHORS, userPsId, appRootPreimage, kmsIssuedPreimage, verifyEnclaveIdentityEvidence, buildMasterSignatureDelivery, encryptMasterSignatureDelivery, type UserPsId, type EnclaveIdentityEvidence, type ExpectedIdentity, type IdentityRequest, type IdentityState, type IdentityResponse, type IdentityRegistrationRequest, type IdentityRegistrationResponse, type MasterSignatureDelivery, type SealedSecretSubmission, type SealedSecretResponse, type AesGcmBox, type SealedEnvelope, type EnclaveTrustAnchors, } from "./protocol/identity.js";
40
41
  export { PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID, PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT, personalServerRegistrationDomain, createViemPersonalServerRegistrationSigner, buildPersonalServerRegistrationTypedData, buildPersonalServerRegistrationSignature, registerPersonalServerSignature, type PersonalServerRegistrationTypedData, type PersonalServerRegistrationSigner, type PersonalServerRegistrationDomainInput, type ViemPersonalServerRegistrationWalletClient, type ViemPersonalServerRegistrationSignerSource, type BuildPersonalServerRegistrationTypedDataInput, type BuildPersonalServerRegistrationSignatureInput, type PersonalServerRegistrationSignature, } from "./protocol/personal-server-registration.js";
41
42
  export { PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION, PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE, PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX, buildPersonalServerLiteOwnerBindingMessage, createViemPersonalServerLiteOwnerBindingSigner, buildPersonalServerLiteOwnerBindingSignature, signPersonalServerLiteOwnerBinding, type PersonalServerLiteOwnerBindingPurpose, type PersonalServerLiteOwnerBindingMessage, type PersonalServerLiteOwnerBindingSigner, type ViemPersonalServerLiteOwnerBindingWalletClient, type ViemPersonalServerLiteOwnerBindingSignerSource, type BuildPersonalServerLiteOwnerBindingSignatureInput, type PersonalServerLiteOwnerBindingSignature, } from "./personal-server-lite/owner-binding.js";
42
43
  export { ACCOUNT_PERSONAL_SERVER_REGISTRATION_INTENT, AccountPersonalServerRegistrationError, signPersonalServerRegistrationWithAccount, type AccountPersonalServerRegistrationIntent, type AccountPersonalServerRegistrationSignature, type AccountPersonalServerRegistrationStatus, type AccountPersonalServerRegistrationRequest, type AccountPersonalServerRegistrationConfig, type AccountSignedPersonalServerRegistration, type AccountConfirmationRequiredPersonalServerRegistration, type AccountFallbackSignedPersonalServerRegistration, type AccountPersonalServerRegistrationResult, } from "./account/personal-server-registration.js";
@@ -51,7 +52,8 @@ export { ScopeSchema, parseScope, scopeToPathSegments, scopeMatchesPattern, scop
51
52
  export { SCOPE_ACTIONS, InvalidScopeEntryError, parseScopeEntry, formatScopeEntry, grantPermissions, permissionsToScopes, tryGrantPermissions, hasAction, type ScopeAction, type ParsedScopeEntry, type GrantPermission, } from "./protocol/scope-actions.js";
52
53
  export { WRITE_SESSION_PATH, WRITE_SIGNATURE_HEADER, WRITE_METADATA_HEADER, WRITE_FILENAME_HEADER, WRITE_CONTENT_DISPOSITION_HEADER, WRITER_ATTRIBUTION_KEY, LINEAGE_KEY, LINEAGE_FIELD, MAX_LINEAGE_SOURCES, RESERVED_WRITE_KEYS, openWriteSession, writeData, writePersonalServerData, sessionCoversScope, binaryWriteSignedBytes, normalizeBinaryMimeType, parseWriteMetadataHeader, encodeWriteMetadataHeader, type WriteTransportRetryOptions, type WriteSession, type OpenWriteSessionParams, type WriteBinaryPayload, type LineageSource, type WriteJsonDataParams, type WriteBinaryDataParams, type WriteDataParams, type WriteDataResult, type WritePersonalServerDataParams, type WritePersonalServerDataResult, type BinaryWriteSignedBytesInput, } from "./protocol/personal-server-write.js";
53
54
  export { resolveWriteSigner, type WriteSigner, type WriteSignerSource, type ViemWriteAccount, type ViemWriteWalletClient, type ResolveWriteSignerOptions, } from "./protocol/write-signer.js";
54
- export { DERIVATIVE_QUESTIONS_PATH, MAX_QUESTION_SOURCE_SCOPES, MAX_QUESTION_CHARS, MAX_QUESTION_MODEL_CHARS, DEFAULT_QUESTION_TIMEOUT_MS, DEFAULT_QUESTION_POLL_INTERVAL_MS, QUESTION_STATUSES, registerQuestion, getQuestion, listQuestions, recomputeQuestion, deleteQuestion, waitForQuestion, askPersonalServer, QuestionStatusSchema, QuestionRegisteredBySchema, DerivativeQuestionSchema, QuestionRecomputeResultSchema, QuestionDeleteResultSchema, type QuestionStatus, type QuestionRegisteredBy, type DerivativeQuestion, type QuestionRecomputeResult, type QuestionDeleteResult, type DerivativeQuestionAuthParams, type RegisterQuestionParams, type GetQuestionParams, type ListQuestionsParams, type RecomputeQuestionParams, type DeleteQuestionParams, type WaitForQuestionParams, type AskPersonalServerParams, type AskPersonalServerResult, } from "./protocol/derivative-questions.js";
55
+ export { DERIVATIVE_QUESTIONS_PATH, MAX_QUESTION_SOURCE_SCOPES, MAX_QUESTION_CHARS, MAX_QUESTION_MODEL_CHARS, DEFAULT_QUESTION_TIMEOUT_MS, DEFAULT_QUESTION_POLL_INTERVAL_MS, QUESTION_STATUSES, DERIVATIVE_ERROR_CODES, DerivativeErrorCodeSchema, type DerivativeErrorCode, registerQuestion, getQuestion, listQuestions, recomputeQuestion, deleteQuestion, waitForQuestion, askPersonalServer, QuestionStatusSchema, QuestionRegisteredBySchema, DerivativeQuestionSchema, QuestionRecomputeResultSchema, QuestionDeleteResultSchema, type QuestionStatus, type QuestionRegisteredBy, type DerivativeQuestion, type QuestionRecomputeResult, type QuestionDeleteResult, type DerivativeQuestionAuthParams, type RegisterQuestionParams, type GetQuestionParams, type ListQuestionsParams, type RecomputeQuestionParams, type DeleteQuestionParams, type WaitForQuestionParams, type AskPersonalServerParams, type AskPersonalServerResult, } from "./protocol/derivative-questions.js";
56
+ export { DERIVATIVE_STATUS_PATH, DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS, DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS, derivativeStatusTarget, getDerivativeStatus, waitForDerivativeStatus, isDerivativeStatusSettled, DerivativeStatusSchema, type DerivativeStatus, type GetDerivativeStatusParams, type WaitForDerivativeStatusParams, } from "./protocol/derivative-status.js";
55
57
  export { deriveDataPointId, isDataPointId, scopeNamespace, derivedScopeViolatesNaming, assertDerivedScopeNaming, isRedactedLineageNode, personalServerLineagePath, gatewayLineagePath, getLineage, getPersonalServerLineage, getGatewayLineage, LineageNodeSchema, RedactedLineageNodeSchema, LineageEntrySchema, LineageGraphSchema, type LineageNode, type RedactedLineageNode, type LineageEntry, type LineageGraph, type LineageReadResult, type PersonalServerLineageParams, type GatewayLineageParams, type GetLineageParams, } from "./protocol/lineage.js";
56
58
  export { DataFileEnvelopeSchema, createDataFileEnvelope, IngestResponseSchema, type DataFileEnvelope, type IngestResponse, } from "./protocol/data-file.js";
57
59
  export { createGatewayClient, type GatewayEnvelope, type GatewayProof, type Builder, type Schema, type ServerInfo, type OwnerServerRecord, type OwnerServersResult, type GatewayGrantFee, type GatewayGrantStatus, type GatewayGrantResponse, type GrantListItem, type DataPointRecord, type DataPointListResult, type ListDataPointsOptions, type RegisterServerParams, type RegisterServerResult, type RegisterBuilderParams, type RegisterBuilderResult, type RegisterDataPointParams, type RegisterDataPointResult, type GetDataPointOptions, type DeleteDataPointParams, type DeleteDataPointResult, type CreateGrantParams, type RevokeGrantParams, type AccessRecord, type PayForOperationParams, type PayForOperationResult, type SettleOpType, type SettleItem, type SettlePromoteResult, type SettleReconcileItem, type SettleParams, type SettleResult, type GatewayClient, } from "./protocol/gateway.js";
@@ -31736,6 +31736,151 @@ var RECORD_DATA_ACCESS_TYPES = {
31736
31736
  ]
31737
31737
  };
31738
31738
 
31739
+ // src/protocol/identity.ts
31740
+ init_interface();
31741
+ import * as secp256k13 from "@noble/secp256k1";
31742
+ import {
31743
+ concat as concat4,
31744
+ encodePacked,
31745
+ fromHex as fromHex5,
31746
+ getAddress,
31747
+ isAddressEqual,
31748
+ keccak256,
31749
+ recoverPublicKey,
31750
+ toBytes,
31751
+ toHex as toHex6
31752
+ } from "viem";
31753
+ import { publicKeyToAddress } from "viem/accounts";
31754
+ var ENCLAVE_IDENTITY_EVIDENCE_VERSION = 1;
31755
+ var USER_PS_ID_DOMAIN = "vana.ps-enclave.v1";
31756
+ var ENCLAVE_WALLET_PURPOSE = "vana.ps-enclave.wallet.v1";
31757
+ var MASTER_SIGNATURE_DELIVERY_VERSION = "vana.ps-enclave.delivery.v1";
31758
+ var SEALED_ENVELOPE_VERSION = 1;
31759
+ var VANA_MAINNET_CHAIN_ID = 1480;
31760
+ var MOKSHA_CHAIN_ID = 14800;
31761
+ var KMS_ISSUED_PREFIX = "dstack-kms-issued";
31762
+ var PREIMAGE_SEPARATOR = ":";
31763
+ var UNCOMPRESSED_PUBLIC_KEY_BYTES = 65;
31764
+ var UNCOMPRESSED_PUBLIC_KEY_PREFIX = "04";
31765
+ var ENCLAVE_TRUST_ANCHORS = {
31766
+ // filled at fleet provisioning; verify fails closed while empty
31767
+ [VANA_MAINNET_CHAIN_ID]: { kmsRootPubkey: "0x", appIds: [] },
31768
+ // filled at fleet provisioning; verify fails closed while empty
31769
+ [MOKSHA_CHAIN_ID]: { kmsRootPubkey: "0x", appIds: [] }
31770
+ };
31771
+ function userPsId(chainId, ownerAddress) {
31772
+ const packed = encodePacked(
31773
+ ["string", "uint256", "address"],
31774
+ [USER_PS_ID_DOMAIN, BigInt(chainId), getAddress(ownerAddress)]
31775
+ );
31776
+ return keccak256(packed);
31777
+ }
31778
+ function compressPublicKey(publicKey) {
31779
+ return secp256k13.ProjectivePoint.fromHex(
31780
+ fromHex5(publicKey, "bytes")
31781
+ ).toRawBytes(true);
31782
+ }
31783
+ function appRootPreimage(purpose, publicKey) {
31784
+ const keyHex = toHex6(compressPublicKey(publicKey)).slice(2);
31785
+ return keccak256(toBytes(`${purpose}${PREIMAGE_SEPARATOR}${keyHex}`));
31786
+ }
31787
+ function kmsIssuedPreimage(appId, appRootPublicKey) {
31788
+ const prefix = concat4([
31789
+ toBytes(`${KMS_ISSUED_PREFIX}${PREIMAGE_SEPARATOR}`),
31790
+ fromHex5(appId, "bytes")
31791
+ ]);
31792
+ const compressed = compressPublicKey(appRootPublicKey);
31793
+ return keccak256(concat4([prefix, compressed]));
31794
+ }
31795
+ async function recoverChainKey(hash, signature, link) {
31796
+ try {
31797
+ return (await recoverPublicKey({ hash, signature })).toLowerCase();
31798
+ } catch {
31799
+ throw new Error(`Invalid enclave signature chain link ${link}`);
31800
+ }
31801
+ }
31802
+ async function verifyEnclaveIdentityEvidence(evidence, anchors, expected) {
31803
+ if (evidence.v !== ENCLAVE_IDENTITY_EVIDENCE_VERSION) {
31804
+ throw new Error("Unsupported enclave identity evidence version");
31805
+ }
31806
+ if (!Number.isInteger(evidence.epoch) || evidence.epoch < 1) {
31807
+ throw new Error("Invalid enclave identity epoch");
31808
+ }
31809
+ if (evidence.chainId !== expected.chainId) {
31810
+ throw new Error(
31811
+ "Enclave identity chain ID does not match expected chain ID"
31812
+ );
31813
+ }
31814
+ if (!isAddressEqual(evidence.ownerAddress, expected.ownerAddress)) {
31815
+ throw new Error("Enclave identity owner does not match expected owner");
31816
+ }
31817
+ if (evidence.epoch !== expected.epoch) {
31818
+ throw new Error("Enclave identity epoch does not match expected epoch");
31819
+ }
31820
+ const expectedUserPsId = userPsId(expected.chainId, expected.ownerAddress);
31821
+ if (evidence.userPsId.toLowerCase() !== expectedUserPsId.toLowerCase()) {
31822
+ throw new Error("Enclave userPsId does not match expected identity");
31823
+ }
31824
+ if (evidence.purpose !== ENCLAVE_WALLET_PURPOSE) {
31825
+ throw new Error("Unexpected enclave wallet purpose");
31826
+ }
31827
+ const derivedAddress = publicKeyToAddress(evidence.publicKey);
31828
+ if (getAddress(derivedAddress) !== getAddress(evidence.address)) {
31829
+ throw new Error("Enclave public key does not match its address");
31830
+ }
31831
+ const appRootPublicKey = await recoverChainKey(
31832
+ appRootPreimage(evidence.purpose, evidence.publicKey),
31833
+ evidence.signatureChain[0],
31834
+ 0
31835
+ );
31836
+ const kmsRootPublicKey = await recoverChainKey(
31837
+ kmsIssuedPreimage(evidence.appId, appRootPublicKey),
31838
+ evidence.signatureChain[1],
31839
+ 1
31840
+ );
31841
+ if (anchors.kmsRootPubkey === "0x") {
31842
+ throw new Error("KMS root trust anchor is not provisioned");
31843
+ }
31844
+ if (kmsRootPublicKey !== anchors.kmsRootPubkey.toLowerCase()) {
31845
+ throw new Error("KMS root public key does not match the trust anchor");
31846
+ }
31847
+ if (keccak256(kmsRootPublicKey) !== evidence.kmsRootFingerprint.toLowerCase()) {
31848
+ throw new Error("KMS root fingerprint does not match the evidence");
31849
+ }
31850
+ const appId = evidence.appId.toLowerCase();
31851
+ if (!anchors.appIds.some((allowedAppId) => allowedAppId.toLowerCase() === appId)) {
31852
+ throw new Error("Enclave app ID is not trusted");
31853
+ }
31854
+ }
31855
+ async function buildMasterSignatureDelivery(evidence, masterSignature, now = Math.floor(Date.now() / 1e3)) {
31856
+ deriveMasterKey(masterSignature);
31857
+ const signerAddress = await recoverServerOwner(masterSignature);
31858
+ if (!isAddressEqual(signerAddress, evidence.ownerAddress)) {
31859
+ throw new Error("Master signature signer does not match evidence owner");
31860
+ }
31861
+ return {
31862
+ v: MASTER_SIGNATURE_DELIVERY_VERSION,
31863
+ userPsId: evidence.userPsId,
31864
+ epoch: evidence.epoch,
31865
+ enclaveAddress: evidence.address,
31866
+ ownerAddress: evidence.ownerAddress,
31867
+ masterSignature,
31868
+ issuedAt: now
31869
+ };
31870
+ }
31871
+ function assertUncompressedKey(publicKey) {
31872
+ const hex = publicKey.slice(2);
31873
+ if (hex.length !== UNCOMPRESSED_PUBLIC_KEY_BYTES * 2 || !hex.startsWith(UNCOMPRESSED_PUBLIC_KEY_PREFIX) || !/^[0-9a-fA-F]+$/.test(hex)) {
31874
+ throw new Error("Public key must be a 65-byte uncompressed secp256k1 key");
31875
+ }
31876
+ }
31877
+ async function encryptMasterSignatureDelivery(delivery, publicKey, ecies) {
31878
+ assertUncompressedKey(publicKey);
31879
+ const plaintext = toBytes(JSON.stringify(delivery));
31880
+ const encrypted = await ecies.encrypt(fromHex5(publicKey, "bytes"), plaintext);
31881
+ return `0x${serializeECIES(encrypted)}`;
31882
+ }
31883
+
31739
31884
  // src/protocol/personal-server-registration.ts
31740
31885
  import {
31741
31886
  isAddress
@@ -32435,7 +32580,7 @@ function buildMarkDataPointUnavailableRequest(config, input) {
32435
32580
  // src/protocol/data-point-deletion.ts
32436
32581
  import {
32437
32582
  isAddress as isAddress5,
32438
- keccak256 as keccak2562,
32583
+ keccak256 as keccak2563,
32439
32584
  maxUint256,
32440
32585
  stringToBytes as stringToBytes3
32441
32586
  } from "viem";
@@ -32444,7 +32589,7 @@ import {
32444
32589
  import {
32445
32590
  encodeAbiParameters,
32446
32591
  isAddress as isAddress4,
32447
- keccak256
32592
+ keccak256 as keccak2562
32448
32593
  } from "viem";
32449
32594
  import { z } from "zod";
32450
32595
 
@@ -32528,7 +32673,7 @@ function deriveDataPointId(ownerAddress, scope) {
32528
32673
  `ownerAddress is not an EVM address: ${String(ownerAddress)}`
32529
32674
  );
32530
32675
  }
32531
- return keccak256(
32676
+ return keccak2562(
32532
32677
  encodeAbiParameters(
32533
32678
  [
32534
32679
  { name: "ownerAddress", type: "address" },
@@ -32755,7 +32900,7 @@ var TOMBSTONE_METADATA_HASH_PREIMAGE = "vana.data-point.tombstone.metadata.v1";
32755
32900
  var TOMBSTONE_DATA_HASH = "0x30c45ee72fe56d1927701316925ab7ceacd3b6f9267061735d59396f075c6222";
32756
32901
  var TOMBSTONE_METADATA_HASH = "0xc5255a141acd6a2ae55971b62c0a85977c2511989dc114ad2abc2b7644f57d90";
32757
32902
  function computeTombstoneHash(preimage) {
32758
- return keccak2562(stringToBytes3(preimage));
32903
+ return keccak2563(stringToBytes3(preimage));
32759
32904
  }
32760
32905
  function isTombstoneHashes(dataHash, metadataHash) {
32761
32906
  return typeof dataHash === "string" && typeof metadataHash === "string" && dataHash.toLowerCase() === TOMBSTONE_DATA_HASH && metadataHash.toLowerCase() === TOMBSTONE_METADATA_HASH;
@@ -33777,6 +33922,13 @@ var QUESTION_STATUSES = [
33777
33922
  "failed",
33778
33923
  "stale"
33779
33924
  ];
33925
+ var DERIVATIVE_ERROR_CODES = [
33926
+ "inference_unavailable",
33927
+ "source_missing",
33928
+ "grant_invalid",
33929
+ "internal"
33930
+ ];
33931
+ var DerivativeErrorCodeSchema = z5.enum(DERIVATIVE_ERROR_CODES);
33780
33932
  var QuestionStatusSchema = z5.enum(QUESTION_STATUSES);
33781
33933
  var QuestionRegisteredBySchema = z5.union([
33782
33934
  z5.object({ kind: z5.literal("owner") }),
@@ -33798,6 +33950,14 @@ var DerivativeQuestionSchema = z5.object({
33798
33950
  status: QuestionStatusSchema,
33799
33951
  /** A short reason, set only while `status` is `failed`. */
33800
33952
  error: nullableString,
33953
+ /**
33954
+ * The coarse failure class behind `error`, set only while `status` is
33955
+ * `failed`. `null` from a Personal Server that predates the class
33956
+ * (`personal-server-ts` before the status route).
33957
+ */
33958
+ errorCode: DerivativeErrorCodeSchema.nullish().transform(
33959
+ (value) => value ?? null
33960
+ ),
33801
33961
  createdAt: z5.string(),
33802
33962
  updatedAt: nullableString,
33803
33963
  /** When the last compute finished, or `null` while `pending`. */
@@ -33930,6 +34090,7 @@ async function questionErrorFromResponse(response, body) {
33930
34090
  );
33931
34091
  }
33932
34092
  }
34093
+ var personalServerErrorFromQuestionResponse = questionErrorFromResponse;
33933
34094
  async function sendOnce(params, resolved, session, spec, bodyBytes) {
33934
34095
  return sendWithFreshProof(
33935
34096
  spec.label,
@@ -34209,6 +34370,166 @@ async function askPersonalServer(params) {
34209
34370
  return { registration, record };
34210
34371
  }
34211
34372
 
34373
+ // src/protocol/derivative-status.ts
34374
+ import { z as z6 } from "zod";
34375
+ var DERIVATIVE_STATUS_PATH = "/v1/derivatives/status";
34376
+ var DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS = 12e4;
34377
+ var DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS = 2e3;
34378
+ var nullable = (schema) => schema.nullish().transform((value) => value ?? null);
34379
+ var DerivativeStatusSchema = z6.object({
34380
+ derivedScope: z6.string().min(1),
34381
+ status: QuestionStatusSchema,
34382
+ /** When the last compute finished, or `null` if none ever has. */
34383
+ lastComputedAt: nullable(z6.string()),
34384
+ /** Local version of the derived record the last compute wrote. */
34385
+ derivedVersion: nullable(z6.number()),
34386
+ derivedCollectedAt: nullable(z6.string()),
34387
+ /** The failure class; `null` unless `status` is `failed`. */
34388
+ errorCode: nullable(DerivativeErrorCodeSchema),
34389
+ /**
34390
+ * Seconds until the Personal Server's next automatic retry, or `null` when
34391
+ * none is pending or running — the terminal signature. Poll on this cadence
34392
+ * rather than guessing one.
34393
+ */
34394
+ retryAfterSeconds: nullable(z6.number())
34395
+ });
34396
+ function derivativeStatusTarget(derivedScope) {
34397
+ return `${DERIVATIVE_STATUS_PATH}?derivedScope=${encodeURIComponent(derivedScope)}`;
34398
+ }
34399
+ function normalizeBaseUrl3(url) {
34400
+ return url.replace(/\/+$/, "");
34401
+ }
34402
+ function resolveFetch3(fetchFn) {
34403
+ const resolved = fetchFn ?? globalThis.fetch;
34404
+ if (resolved === void 0) {
34405
+ throw new WriteRequestError("No fetch implementation available");
34406
+ }
34407
+ return resolved;
34408
+ }
34409
+ function requireDerivedScope(derivedScope) {
34410
+ if (typeof derivedScope !== "string" || derivedScope.length === 0) {
34411
+ throw new WriteRequestError("derivedScope is required");
34412
+ }
34413
+ return derivedScope;
34414
+ }
34415
+ function sleep3(ms, signal) {
34416
+ if (ms <= 0) return Promise.resolve();
34417
+ return new Promise((resolve, reject) => {
34418
+ const timer = setTimeout(() => {
34419
+ signal?.removeEventListener("abort", onAbort);
34420
+ resolve();
34421
+ }, ms);
34422
+ const onAbort = () => {
34423
+ clearTimeout(timer);
34424
+ reject(abortError2(signal));
34425
+ };
34426
+ signal?.addEventListener("abort", onAbort, { once: true });
34427
+ });
34428
+ }
34429
+ function timeoutError(latest, timeoutMs) {
34430
+ return new DerivativeQuestionTimeoutError(
34431
+ `Derived scope ${latest.derivedScope} was still ${latest.status} after ${timeoutMs}ms`,
34432
+ {
34433
+ derivedScope: latest.derivedScope,
34434
+ status: latest.status,
34435
+ errorCode: latest.errorCode,
34436
+ retryAfterSeconds: latest.retryAfterSeconds,
34437
+ timeoutMs
34438
+ }
34439
+ );
34440
+ }
34441
+ function abortError2(signal) {
34442
+ const reason = signal?.reason;
34443
+ return reason instanceof Error ? reason : new WriteRequestError("Derivative status wait was aborted");
34444
+ }
34445
+ function isDerivativeStatusSettled(status) {
34446
+ if (status.status === "ready") return true;
34447
+ return status.status === "failed" && status.retryAfterSeconds === null;
34448
+ }
34449
+ async function getDerivativeStatus(params) {
34450
+ const derivedScope = requireDerivedScope(params.derivedScope);
34451
+ const fetchFn = resolveFetch3(params.fetch);
34452
+ const baseUrl = normalizeBaseUrl3(params.personalServerUrl);
34453
+ const signer = resolveWriteSigner(params.signer, { account: params.account });
34454
+ const headers = new Headers(params.headers);
34455
+ headers.set(
34456
+ "Authorization",
34457
+ await buildWeb3SignedHeader({
34458
+ signMessage: signer.signMessage,
34459
+ aud: params.audience ?? baseUrl,
34460
+ method: "GET",
34461
+ uri: DERIVATIVE_STATUS_PATH,
34462
+ grantId: params.grantId
34463
+ })
34464
+ );
34465
+ let response;
34466
+ try {
34467
+ response = await fetchFn(
34468
+ `${baseUrl}${derivativeStatusTarget(derivedScope)}`,
34469
+ {
34470
+ method: "GET",
34471
+ headers,
34472
+ ...params.signal ? { signal: params.signal } : {}
34473
+ }
34474
+ );
34475
+ } catch (err) {
34476
+ throw new WriteTransportError(
34477
+ `Derivative status read failed: ${err instanceof Error ? err.message : String(err)}`,
34478
+ 1,
34479
+ err
34480
+ );
34481
+ }
34482
+ if (!response.ok) {
34483
+ throw await personalServerErrorFromQuestionResponse(
34484
+ response
34485
+ );
34486
+ }
34487
+ let body;
34488
+ try {
34489
+ body = await response.json();
34490
+ } catch (err) {
34491
+ throw new DerivativeQuestionRejectedError(
34492
+ "Derivative status response is not JSON",
34493
+ response.status,
34494
+ null,
34495
+ { cause: err instanceof Error ? err.message : String(err) }
34496
+ );
34497
+ }
34498
+ const parsed = DerivativeStatusSchema.safeParse(body);
34499
+ if (!parsed.success) {
34500
+ throw new DerivativeQuestionRejectedError(
34501
+ "Derivative status response is not a status view",
34502
+ response.status,
34503
+ null,
34504
+ { issues: parsed.error.issues }
34505
+ );
34506
+ }
34507
+ return parsed.data;
34508
+ }
34509
+ async function waitForDerivativeStatus(params) {
34510
+ const timeoutMs = Math.max(
34511
+ 0,
34512
+ params.timeoutMs ?? DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS
34513
+ );
34514
+ const pollIntervalMs = Math.max(
34515
+ 0,
34516
+ params.pollIntervalMs ?? DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS
34517
+ );
34518
+ const deadline = Date.now() + timeoutMs;
34519
+ for (; ; ) {
34520
+ if (params.signal?.aborted) throw abortError2(params.signal);
34521
+ const latest = await getDerivativeStatus(params);
34522
+ if (isDerivativeStatusSettled(latest)) return latest;
34523
+ const remaining = deadline - Date.now();
34524
+ if (remaining <= 0) throw timeoutError(latest, timeoutMs);
34525
+ const waitMs = latest.retryAfterSeconds === null ? pollIntervalMs : latest.retryAfterSeconds * 1e3;
34526
+ if (waitMs > remaining) {
34527
+ throw timeoutError(latest, timeoutMs);
34528
+ }
34529
+ await sleep3(waitMs, params.signal);
34530
+ }
34531
+ }
34532
+
34212
34533
  // src/protocol/gateway.ts
34213
34534
  function withGrantPermissions(grant) {
34214
34535
  const stripped = { ...grant };
@@ -34821,9 +35142,13 @@ export {
34821
35142
  ContractFactory,
34822
35143
  ContractNotFoundError,
34823
35144
  DATA_REGISTRY_STATUS_ABI,
35145
+ DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS,
35146
+ DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS,
34824
35147
  DEFAULT_QUESTION_POLL_INTERVAL_MS,
34825
35148
  DEFAULT_QUESTION_TIMEOUT_MS,
35149
+ DERIVATIVE_ERROR_CODES,
34826
35150
  DERIVATIVE_QUESTIONS_PATH,
35151
+ DERIVATIVE_STATUS_PATH,
34827
35152
  DataFileEnvelopeSchema,
34828
35153
  DataPointDeletedError,
34829
35154
  DataPointNotFoundError,
@@ -34832,6 +35157,7 @@ export {
34832
35157
  DerivativeComputeUnavailableError,
34833
35158
  DerivativeCycleError,
34834
35159
  DerivativeDerivedScopeRequiredError,
35160
+ DerivativeErrorCodeSchema,
34835
35161
  DerivativeQuestionFailedError,
34836
35162
  DerivativeQuestionInvalidError,
34837
35163
  DerivativeQuestionNotFoundError,
@@ -34839,8 +35165,12 @@ export {
34839
35165
  DerivativeQuestionSchema,
34840
35166
  DerivativeQuestionTimeoutError,
34841
35167
  DerivativeSourceNotGrantedError,
35168
+ DerivativeStatusSchema,
34842
35169
  DropboxStorage,
34843
35170
  ECIESError,
35171
+ ENCLAVE_IDENTITY_EVIDENCE_VERSION,
35172
+ ENCLAVE_TRUST_ANCHORS,
35173
+ ENCLAVE_WALLET_PURPOSE,
34844
35174
  ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
34845
35175
  ExpiredTokenError,
34846
35176
  FEE_REGISTRY_ABI,
@@ -34861,6 +35191,7 @@ export {
34861
35191
  LineageNodeSchema,
34862
35192
  LineageReadError,
34863
35193
  MASTER_KEY_MESSAGE,
35194
+ MASTER_SIGNATURE_DELIVERY_VERSION,
34864
35195
  MAX_LINEAGE_SOURCES,
34865
35196
  MAX_QUESTION_CHARS,
34866
35197
  MAX_QUESTION_MODEL_CHARS,
@@ -34896,6 +35227,7 @@ export {
34896
35227
  RedactedLineageNodeSchema,
34897
35228
  RelayerError,
34898
35229
  SCOPE_ACTIONS,
35230
+ SEALED_ENVELOPE_VERSION,
34899
35231
  SERVER_REGISTRATION_TYPES,
34900
35232
  ScopeSchema,
34901
35233
  SerializationError,
@@ -34908,6 +35240,7 @@ export {
34908
35240
  TOMBSTONE_METADATA_HASH,
34909
35241
  TOMBSTONE_METADATA_HASH_PREIMAGE,
34910
35242
  TransactionPendingError,
35243
+ USER_PS_ID_DOMAIN,
34911
35244
  UserRejectedRequestError,
34912
35245
  VanaError,
34913
35246
  VanaStorage,
@@ -34926,6 +35259,7 @@ export {
34926
35259
  WriteSessionExpiredError,
34927
35260
  WriteTransportError,
34928
35261
  WriteUnauthorizedError,
35262
+ appRootPreimage,
34929
35263
  askPersonalServer,
34930
35264
  assertDerivedScopeNaming,
34931
35265
  assertValidPkceVerifier,
@@ -34935,6 +35269,7 @@ export {
34935
35269
  buildDepositNativeRequest,
34936
35270
  buildDepositTokenRequest,
34937
35271
  buildMarkDataPointUnavailableRequest,
35272
+ buildMasterSignatureDelivery,
34938
35273
  buildPersonalServerDataReadRequest,
34939
35274
  buildPersonalServerLiteOwnerBindingMessage,
34940
35275
  buildPersonalServerLiteOwnerBindingSignature,
@@ -34963,6 +35298,7 @@ export {
34963
35298
  decryptWithPassword,
34964
35299
  deleteDataPoint,
34965
35300
  deleteQuestion,
35301
+ derivativeStatusTarget,
34966
35302
  deriveDataPointId,
34967
35303
  deriveMasterKey,
34968
35304
  deriveScopeKey,
@@ -34973,6 +35309,7 @@ export {
34973
35309
  encodeDepositTokenData,
34974
35310
  encodeSetDataPointStatusData,
34975
35311
  encodeWriteMetadataHeader,
35312
+ encryptMasterSignatureDelivery,
34976
35313
  encryptWithPassword,
34977
35314
  escrowContractAddress,
34978
35315
  escrowPaymentDomain,
@@ -34986,6 +35323,7 @@ export {
34986
35323
  getContractAddress,
34987
35324
  getContractController,
34988
35325
  getContractInfo,
35326
+ getDerivativeStatus,
34989
35327
  getFee,
34990
35328
  getGatewayLineage,
34991
35329
  getLineage,
@@ -35001,10 +35339,12 @@ export {
35001
35339
  isDataPointId,
35002
35340
  isDataPointTombstone,
35003
35341
  isDataPortabilityGatewayConfig,
35342
+ isDerivativeStatusSettled,
35004
35343
  isECIESEncrypted,
35005
35344
  isPlatformSupported,
35006
35345
  isRedactedLineageNode,
35007
35346
  isTombstoneHashes,
35347
+ kmsIssuedPreimage,
35008
35348
  listQuestions,
35009
35349
  mainnetServices,
35010
35350
  moksha,
@@ -35039,10 +35379,13 @@ export {
35039
35379
  signPersonalServerRegistrationWithAccount,
35040
35380
  tombstoneDeletedAt,
35041
35381
  tryGrantPermissions,
35382
+ userPsId,
35042
35383
  vanaMainnet2 as vanaMainnet,
35384
+ verifyEnclaveIdentityEvidence,
35043
35385
  verifyGrantRegistration,
35044
35386
  verifyPkceChallenge,
35045
35387
  verifyWeb3Signed,
35388
+ waitForDerivativeStatus,
35046
35389
  waitForQuestion,
35047
35390
  writeData,
35048
35391
  writePersonalServerData