@layervai/qurl 0.7.0 → 3.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.
Files changed (121) hide show
  1. package/README.md +242 -2
  2. package/dist/cjs/client.d.ts +41 -9
  3. package/dist/cjs/client.js +734 -41
  4. package/dist/cjs/crid.d.ts +2 -1
  5. package/dist/cjs/crid.js +11 -2
  6. package/dist/cjs/errors.d.ts +20 -3
  7. package/dist/cjs/errors.js +31 -4
  8. package/dist/cjs/index.d.ts +2 -2
  9. package/dist/cjs/index.js +3 -1
  10. package/dist/cjs/node/agent-runtime.d.ts +108 -0
  11. package/dist/cjs/node/agent-runtime.js +952 -0
  12. package/dist/cjs/node/agent-state.d.ts +100 -0
  13. package/dist/cjs/node/agent-state.js +311 -0
  14. package/dist/cjs/node/agent-transport.d.ts +17 -0
  15. package/dist/cjs/node/agent-transport.js +118 -0
  16. package/dist/cjs/node/deployment.d.ts +6 -0
  17. package/dist/cjs/node/deployment.js +24 -3
  18. package/dist/cjs/node/file-agent-state.d.ts +15 -0
  19. package/dist/cjs/node/file-agent-state.js +137 -0
  20. package/dist/cjs/node/native-loader.cjs +7 -0
  21. package/dist/cjs/node/native-loader.d.cts +11 -0
  22. package/dist/cjs/node/native-udp.d.ts +8 -3
  23. package/dist/cjs/node/native-udp.js +8 -3
  24. package/dist/cjs/node/nhp-wire.d.ts +9 -0
  25. package/dist/cjs/node/nhp-wire.js +24 -7
  26. package/dist/cjs/node/portal-opener.d.ts +7 -0
  27. package/dist/cjs/node/portal-opener.js +28 -6
  28. package/dist/cjs/node/provider.d.ts +19 -0
  29. package/dist/cjs/node/provider.js +153 -0
  30. package/dist/cjs/node/qv2.d.ts +3 -1
  31. package/dist/cjs/node/qv2.js +16 -2
  32. package/dist/cjs/node/relay.d.ts +12 -0
  33. package/dist/cjs/node/relay.js +111 -0
  34. package/dist/cjs/node/sealed-agent-state.d.ts +19 -0
  35. package/dist/cjs/node/sealed-agent-state.js +193 -0
  36. package/dist/cjs/node/strict-json.d.ts +1 -1
  37. package/dist/cjs/node/strict-json.js +8 -3
  38. package/dist/cjs/node.d.ts +14 -0
  39. package/dist/cjs/node.js +24 -1
  40. package/dist/cjs/types.d.ts +161 -8
  41. package/dist/cjs/version.d.ts +1 -1
  42. package/dist/cjs/version.js +1 -1
  43. package/dist/esm/client.d.ts +41 -9
  44. package/dist/esm/client.d.ts.map +1 -1
  45. package/dist/esm/client.js +735 -42
  46. package/dist/esm/client.js.map +1 -1
  47. package/dist/esm/crid.d.ts +2 -1
  48. package/dist/esm/crid.d.ts.map +1 -1
  49. package/dist/esm/crid.js +10 -2
  50. package/dist/esm/crid.js.map +1 -1
  51. package/dist/esm/errors.d.ts +20 -3
  52. package/dist/esm/errors.d.ts.map +1 -1
  53. package/dist/esm/errors.js +29 -3
  54. package/dist/esm/errors.js.map +1 -1
  55. package/dist/esm/index.d.ts +2 -2
  56. package/dist/esm/index.d.ts.map +1 -1
  57. package/dist/esm/index.js +1 -1
  58. package/dist/esm/index.js.map +1 -1
  59. package/dist/esm/node/agent-runtime.d.ts +109 -0
  60. package/dist/esm/node/agent-runtime.d.ts.map +1 -0
  61. package/dist/esm/node/agent-runtime.js +946 -0
  62. package/dist/esm/node/agent-runtime.js.map +1 -0
  63. package/dist/esm/node/agent-state.d.ts +101 -0
  64. package/dist/esm/node/agent-state.d.ts.map +1 -0
  65. package/dist/esm/node/agent-state.js +298 -0
  66. package/dist/esm/node/agent-state.js.map +1 -0
  67. package/dist/esm/node/agent-transport.d.ts +18 -0
  68. package/dist/esm/node/agent-transport.d.ts.map +1 -0
  69. package/dist/esm/node/agent-transport.js +114 -0
  70. package/dist/esm/node/agent-transport.js.map +1 -0
  71. package/dist/esm/node/deployment.d.ts +6 -0
  72. package/dist/esm/node/deployment.d.ts.map +1 -1
  73. package/dist/esm/node/deployment.js +23 -3
  74. package/dist/esm/node/deployment.js.map +1 -1
  75. package/dist/esm/node/file-agent-state.d.ts +16 -0
  76. package/dist/esm/node/file-agent-state.d.ts.map +1 -0
  77. package/dist/esm/node/file-agent-state.js +134 -0
  78. package/dist/esm/node/file-agent-state.js.map +1 -0
  79. package/dist/esm/node/native-loader.cjs +7 -0
  80. package/dist/esm/node/native-loader.d.cts +11 -0
  81. package/dist/esm/node/native-udp.d.ts +8 -3
  82. package/dist/esm/node/native-udp.d.ts.map +1 -1
  83. package/dist/esm/node/native-udp.js +7 -5
  84. package/dist/esm/node/native-udp.js.map +1 -1
  85. package/dist/esm/node/nhp-wire.d.ts +9 -0
  86. package/dist/esm/node/nhp-wire.d.ts.map +1 -1
  87. package/dist/esm/node/nhp-wire.js +23 -6
  88. package/dist/esm/node/nhp-wire.js.map +1 -1
  89. package/dist/esm/node/portal-opener.d.ts +7 -0
  90. package/dist/esm/node/portal-opener.d.ts.map +1 -1
  91. package/dist/esm/node/portal-opener.js +28 -6
  92. package/dist/esm/node/portal-opener.js.map +1 -1
  93. package/dist/esm/node/provider.d.ts +20 -0
  94. package/dist/esm/node/provider.d.ts.map +1 -0
  95. package/dist/esm/node/provider.js +149 -0
  96. package/dist/esm/node/provider.js.map +1 -0
  97. package/dist/esm/node/qv2.d.ts +3 -1
  98. package/dist/esm/node/qv2.d.ts.map +1 -1
  99. package/dist/esm/node/qv2.js +17 -3
  100. package/dist/esm/node/qv2.js.map +1 -1
  101. package/dist/esm/node/relay.d.ts +13 -0
  102. package/dist/esm/node/relay.d.ts.map +1 -0
  103. package/dist/esm/node/relay.js +105 -0
  104. package/dist/esm/node/relay.js.map +1 -0
  105. package/dist/esm/node/sealed-agent-state.d.ts +20 -0
  106. package/dist/esm/node/sealed-agent-state.d.ts.map +1 -0
  107. package/dist/esm/node/sealed-agent-state.js +190 -0
  108. package/dist/esm/node/sealed-agent-state.js.map +1 -0
  109. package/dist/esm/node/strict-json.d.ts +1 -1
  110. package/dist/esm/node/strict-json.d.ts.map +1 -1
  111. package/dist/esm/node/strict-json.js +8 -3
  112. package/dist/esm/node/strict-json.js.map +1 -1
  113. package/dist/esm/node.d.ts +14 -0
  114. package/dist/esm/node.d.ts.map +1 -1
  115. package/dist/esm/node.js +7 -0
  116. package/dist/esm/node.js.map +1 -1
  117. package/dist/esm/types.d.ts +161 -8
  118. package/dist/esm/types.d.ts.map +1 -1
  119. package/dist/esm/version.d.ts +1 -1
  120. package/dist/esm/version.js +1 -1
  121. package/package.json +16 -6
package/README.md CHANGED
@@ -182,7 +182,16 @@ console.log(share.qurlId); // Safe handle for revoking only this link later
182
182
  `shareResource` returns the current share-safe `#qv2t1...` link. Recipients
183
183
  open that URL in the qURL browser flow. For native TypeScript opening, pass
184
184
  `share.link` to `createPortalOpener` from `@layervai/qurl/node` with trusted
185
- `QURL_DEPLOYMENT` configuration. See the native opener example above.
185
+ `QURL_DEPLOYMENT` configuration and `expectedCRID: advertisedCRID`.
186
+ Obtain `advertisedCRID` independently of the response carrying the link.
187
+ The opener verifies the issuer signature and CRID/key binding before each
188
+ native access request, including renewals. Empty, malformed, unsupported,
189
+ and mismatched CRIDs fail closed. Omitting the option retains link-only access.
190
+ This verifies resource identity, not content or current revocation state.
191
+ The access-binding check accepts only locally registered versions and their
192
+ registered digest widths, matching the Go SDK and browser agent. Upgrade the
193
+ SDK when a new version is activated. This is stricter than the forwarding
194
+ and supplied-key helper below. See the native opener example below.
186
195
  `verifyCrid` does not open the link or make a network request.
187
196
 
188
197
  `verifyCrid` verifies that the response CRID derives from the trusted resource
@@ -259,6 +268,74 @@ await client.updateApiKey(keyId, { scopes });
259
268
  This credential surface requires the kind-first qurl-service contract at or
260
269
  after commit `047cf31e1cdf545e3060e0f9294d738a19fb997b`.
261
270
 
271
+ ## Delegated qURL batches
272
+
273
+ Services with a delegated mint capability can create up to 100 ordered grants
274
+ without an API call per recipient:
275
+
276
+ ```typescript
277
+ import { DelegatedBatchOutcomeUnknownError, QURLClient } from '@layervai/qurl';
278
+
279
+ const client = new QURLClient({ apiKey: process.env.QURL_API_KEY! });
280
+ const key = crypto.randomUUID();
281
+ const mintCapability = process.env.QURL_MINT_CAPABILITY!;
282
+ const recipients = [{ name: 'Alice' }];
283
+
284
+ const accepted = await client
285
+ .createDelegatedQurlBatch(
286
+ {
287
+ mint_capability: mintCapability,
288
+ grants: recipients.map((recipient) => ({ label: recipient.name, expires_in: '1h' })),
289
+ },
290
+ { idempotencyKey: key },
291
+ )
292
+ .catch((error: unknown) => {
293
+ if (error instanceof DelegatedBatchOutcomeUnknownError && error.batchId) {
294
+ console.error('Poll the accepted batch before retrying', { batchId: error.batchId });
295
+ }
296
+ // A deliberate retry must reuse this key and exact body.
297
+ throw error;
298
+ });
299
+
300
+ let etag = accepted.etag;
301
+ let retryAfter = accepted.retry_after;
302
+ let state;
303
+ const deadline = Date.now() + 60_000;
304
+ for (let polls = 0; polls < 30 && Date.now() < deadline; polls++) {
305
+ await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
306
+ state = await client.getDelegatedQurlBatch(accepted.batch_id, { etag });
307
+ if (state.http_status === 304) {
308
+ retryAfter = state.retry_after ?? retryAfter;
309
+ } else if (state.http_status === 202) {
310
+ ({ etag, retry_after: retryAfter } = state);
311
+ } else {
312
+ break;
313
+ }
314
+ }
315
+
316
+ if (state?.http_status !== 200) throw new Error('Delegated qURL batch did not finish');
317
+
318
+ if (state.results[0]?.status === 'succeeded') {
319
+ const qurlId = state.results[0].qurl.qurl_id;
320
+ const metadata = await client.getDelegatedQurl(qurlId);
321
+ console.log(metadata.status);
322
+ await client.deleteDelegatedQurl(qurlId);
323
+ }
324
+ ```
325
+
326
+ The idempotency key must contain 32–256 visible ASCII characters. A UUID meets
327
+ this requirement.
328
+
329
+ One read makes one HTTP attempt. The caller owns the poll count, total deadline,
330
+ and wait from `retry_after`. A `304` means the prior ETag is still current. A
331
+ `200` contains the terminal, input-ordered results. Keep each returned qURL as
332
+ an opaque bearer link and apply any deployment-specific origin check before
333
+ publishing it.
334
+
335
+ Delegated DELETE calls are not retried automatically. After a transport failure
336
+ or `503 mutation_outcome_unknown`, retry the same qURL ID until the service
337
+ returns `204`.
338
+
262
339
  ## Opening Portals
263
340
 
264
341
  Most recipients open qURL links directly and do not use this SDK at all. If
@@ -298,6 +375,7 @@ const { createPortalOpener } = require('@layervai/qurl/node');
298
375
  async function uploadPrivateObject(uploadBody) {
299
376
  const opener = createPortalOpener({
300
377
  qurl: process.env.PRIVATE_UPLOAD_QURL,
378
+ expectedCRID: process.env.PRIVATE_UPLOAD_CRID ?? '', // Independently held; missing fails closed.
301
379
  });
302
380
  try {
303
381
  await opener.start();
@@ -512,7 +590,9 @@ console.log(`Access granted to ${access.target_url} for ${access.access_grant?.e
512
590
  | `createApiKey(input)` / `listApiKeys(input?)` / `listAllApiKeys(input?)` / `updateApiKey(id, input)` / `revokeApiKey(id)` | API key management |
513
591
  | `createAccessCode(input)` / `listAccessCodes()` / `redeemAccessCode(input)` / `revokeAccessCode(id)` | Access code management |
514
592
 
515
- `listResourceSessions(id)` and `listAccessCodes()` reflect currently unpaginated service endpoints. Their outputs always return `has_more: false`; if the service starts surfacing cursor metadata, the SDK emits a debug log rather than exposing an unactionable next-page signal.
593
+ `listResourceSessions(id)` opts in to bounded pages with `paged=true` and collects every service page, including empty intermediate pages, and returns `has_more: false`. Its `request_id` and `page_size` describe the last page. `terminateAllResourceSessions(id)` follows every page and sums closed sessions. Termination is not atomic: an error can occur after some sessions close. List sessions to reconcile before retrying; a retry can also close newly admitted sessions and counts only its own changes. A successful call returns the last page’s `request_id`.
594
+
595
+ `listAccessCodes()` remains unpaginated. It returns `has_more: false` and logs unexpected cursor metadata.
516
596
 
517
597
  `listAll*()` methods validate ids and query params when called, before the async iterator is consumed. Wrap the `listAll*()` call itself in `try/catch` when passing dynamic input.
518
598
 
@@ -585,6 +665,7 @@ try {
585
665
  | `ServerError` | 5xx | Server-side failure |
586
666
  | `NetworkError` | — | Connection failure |
587
667
  | `TimeoutError` | — | Request exceeded timeout |
668
+ | `DelegatedBatchOutcomeUnknownError` | — | Dispatched batch create needs reconciliation |
588
669
 
589
670
  Client-detected failures use `status: 0` with a discriminating `code`:
590
671
  `"client_validation"` for bad input caught before a request, and — on the
@@ -757,3 +838,162 @@ MIT
757
838
  Resource verification requires Web Crypto (`crypto.subtle`). In browsers, use
758
839
  an HTTPS page or localhost. Raw REST response types keep `crid` optional;
759
840
  resource handles and portals require a validated CRID.
841
+
842
+ ## Node producer runtime (SDK 2.x, NHP 1.1)
843
+
844
+ The SDK implements the producer lifecycle in TypeScript. A small optional native
845
+ package, `@layervai/qurl-state-fs`, supplies descriptor-relative filesystem
846
+ operations on Linux and macOS. There is no bundled Go runtime. The portable
847
+ `@layervai/qurl` entry point does not load the native module.
848
+
849
+ ```ts
850
+ import { FileAgentState, connectAgentRuntime } from '@layervai/qurl/node';
851
+
852
+ const store = new FileAgentState('/private/agent/state.json');
853
+ const runtime = await connectAgentRuntime(store, {
854
+ hub: { host: 'hub.nhp.layerv.ai', port: 443, server_public_key_b64: hubPublicKey },
855
+ headless: true,
856
+ enrollmentCredential: bootstrapCredential,
857
+ });
858
+ try {
859
+ // runtime.client uses the durable device credential, with bounded reloads.
860
+ const grant = await runtime.knock(knockResourceID, {
861
+ protectedResourceID: crid, runID: '0123456789abcdef', runAttempt: 1n,
862
+ });
863
+ // Keep the original receipt. It retains the issuing cell across relocation.
864
+ await runtime.retire(grant.receipt);
865
+ } finally {
866
+ await runtime.close();
867
+ store.close();
868
+ }
869
+ ```
870
+
871
+ A registered state opens without enrollment or network work while its assignment
872
+ lease is current. An explicit Hub option or the `hub` field in `QURL_DEPLOYMENT`
873
+ provides refresh trust. `runtime.refresh()` handles assignment renewal and
874
+ relocation. `knock()` attempts renewal near lease expiry and refuses expired
875
+ assignments. Account enrollment uses an explicit `otpProvider` instead of
876
+ `headless`. Resume an interrupted enrollment with the same credential and
877
+ metadata. The SDK persists activation and completion replay authority before
878
+ sending the corresponding mutation.
879
+
880
+ `recoverAgentRuntime(store, recoveryCredential, { hub })` starts explicit device
881
+ credential recovery. It persists the issue nonce, replacement candidate, and
882
+ recovery horizon. It saves the recovered credential before mandatory assignment
883
+ refresh. A failed refresh resumes without another recovery grant. No startup
884
+ path silently resets an existing identity.
885
+
886
+ Legacy pre-v6 pending-completion state remains readable, but enrollment returns
887
+ `RECOVERY_MIGRATION_REQUIRED` without UDP or state changes. Those records lack
888
+ an authenticated recovery deadline; explicit recovery or reprovisioning is required.
889
+ Filesystem state creation honors the process umask and creates missing ancestors.
890
+ Keep owner read/write/search permissions enabled (for example, umask `077`);
891
+ unsafe existing permissions or an incompatible umask fail closed.
892
+
893
+ `FileAgentState` uses a private directory, mode 0600 files, a process-safe setup
894
+ lock, exclusive temporary files, file and directory fsync, and atomic replacement.
895
+ It rejects symlinks, hard links, unsafe permissions, and directory or lock
896
+ replacement. Await `runtime.close()` before closing the store. Inside `withLock`,
897
+ use the supplied locked handle; using the outer store waits until the lock timeout.
898
+ Crash-abandoned `.qurl-*` temporary files remain private but need offline cleanup;
899
+ automatic sweeps could race other state files in the same directory. Filesystem state
900
+ uses synchronous native I/O, including fsync, on the event loop. Use local storage;
901
+ slow or network filesystems can block the process. Continuity checks also run before
902
+ lifecycle datagrams and cannot be cached safely across external directory changes.
903
+ An existing state directory must be owned by the process user with mode 0700.
904
+ On macOS, `/var`, `/tmp`, and `/etc` resolve through their standard `/private` paths.
905
+ A save error after rename can mean the new state is present but its durability is
906
+ unconfirmed; do not assume the previous state remains. Filesystem state
907
+ currently requires Linux or macOS; unsupported platforms fail closed. Install
908
+ scripts may be disabled when a matching prebuilt native binary is available.
909
+ Linux x64/arm64 prebuilds distinguish glibc and musl; CI tests Ubuntu 24.04 and
910
+ Alpine 3.22. macOS prebuilds cover x64 and arm64.
911
+
912
+ For sealed state, use `openSealedFileAgentState(path, providerID, keyWrapper,
913
+ expectedAgentID)`. Each save uses a fresh AES-256-GCM key and verifies wrapping and
914
+ unwrapping before commit. The envelope is compatible with the pinned Go SDK.
915
+ Sealing authenticates the agent, provider, purpose, version, and wrapped-key
916
+ metadata. It does not detect rollback to an older valid envelope. JavaScript
917
+ strings cannot be reliably erased; avoid logging state or credentials.
918
+
919
+ AWS adapters are separate exports from `@layervai/qurl-aws` (ESM and CommonJS).
920
+ Install the AWS client for the subpath you use: `/ssm`, `/secrets-manager`, or
921
+ `/kms`. These clients are optional peer dependencies. Importing the root barrel
922
+ requires all three clients.
923
+
924
+
925
+ - `createSSMAgentStateStore(ssmClient, parameterName, { kmsKeyID, tier })` stores
926
+ SecureString parameters and enforces tier size limits.
927
+ - `createSecretsManagerAgentStateStore(secretsClient, secretID, kmsKeyID)` handles
928
+ missing-secret creation races with one write token.
929
+ - `createKMSAgentStateKeyWrapper(kmsClient, keyID)` wraps only the data key and
930
+ authenticates all four state-binding fields in the KMS encryption context.
931
+
932
+ SSM and Secrets Manager stores serialize lifecycle calls within one store handle.
933
+ Loads outside a lifecycle lock can read the previous committed state.
934
+ They require one process to own each state object: these services do not provide
935
+ an agent setup transaction lock. KMS is a key wrapper, not a state store.
936
+
937
+ ## Explicit relay and discovery
938
+
939
+ Native UDP remains the default transport. An unknown native cell fails closed, including
940
+ when a relay allowlist exists. Select `transport: 'relay'` explicitly to use HTTPS
941
+ relay. Explicit relay trust uses signed qv2 claims and the relay allowlist, not
942
+ the native cell catalog. Relay URLs must match that deployment trust.
943
+ Redirects and oversized responses are refused. A hostname-only allowlist entry
944
+ authorizes all ports on that host; use `host:port` to limit the port.
945
+
946
+ `createStaticProvider(deployment)` snapshots fixed trust. For discovery, use
947
+ `createDiscoveryProvider({ fetcher, pinSHA256, manifestKeys, requireSignature,
948
+ minVersion, expectedProfile })` and `createHTTPManifestFetcher(httpsURL)`. Supply
949
+ a manifest pin or signing keys. Discovery is relay-only and requires
950
+ `transport: 'relay'`; native UDP requires a static cell catalog. Discovery verifies the domain-separated low-S
951
+ signature when configured, validity times, profile, and monotonic version floor.
952
+ It never returns stale trust after a failed refresh. Persist `minVersion` in
953
+ configuration when downgrade protection must survive process restarts.
954
+ Like Go, discovery fetches on each resolution, including renewal retries; it has
955
+ no built-in cache. Use static trust for high-volume opens, or supply a provider
956
+ with a deployment-owned refresh policy that refuses expired or failed-refresh trust.
957
+
958
+ ```ts
959
+ const opener = createPortalOpener({ qurl: signedLink, provider, transport: 'relay' });
960
+ ```
961
+
962
+ The SHA-pinned reviewed baseline and behavior gates are in `parity-manifest.json`.
963
+ CI reports the candidate SHA and tests that candidate against pinned Go behavior.
964
+ It does not require release or dependency PRs to match the baseline tree.
965
+ Run `npm run build`, `npm test`, `npm run smoke:dist`, and `npm run parity:go`.
966
+ Set `QURL_GO_REFERENCE` to a clean checkout at the manifest's exact Go revision.
967
+ The direct gate compares producer wire bytes and sealed-state reads and writes
968
+ across both languages. It also runs the TypeScript lifecycle against a local Go UDP
969
+ peer: registration, restart, relocation, exact retirement, and credential recovery.
970
+ This checks protocol interoperability; the peer is not a sandbox authority.
971
+ Shared conformance vectors cover assignment, registration,
972
+ OTP, and completion packet construction and reply decryption.
973
+
974
+
975
+ ### Private consumer policies
976
+
977
+ `createResource` accepts `private: true` and `consumer_access` with mode
978
+ `keys`, `invite_only`, `email_capture`, `review` or `contract`, and version `1`.
979
+ `updateResource` changes the policy with `expected_consumer_access_version` and
980
+ the next version. Send policy changes separately from metadata updates.
981
+
982
+ For a URL, `protectUrl(url, { consumerAccess: { mode: "invite_only", version: 1 } })`
983
+ creates the private resource and checks the returned policy. For a local
984
+ Connector, pass the policy as the third argument to `ensureConnectorResource`.
985
+ A private policy cannot be combined with public access. A service that ignores
986
+ the requested policy is refused.
987
+
988
+ Publisher methods are `inviteConsumer`, `listConsumerInvitations`,
989
+ `resendConsumerInvitation`, `revokeConsumerInvitation`, `listConsumerGrants`,
990
+ `approveConsumerGrant`, `denyConsumerGrant` and `revokeConsumerGrant`. Decisions
991
+ use the version read from the invitation or grant. Lists return the usual
992
+ `nextCursor`. Contract entitlement approval requires a trusted publisher backend
993
+ receipt and expiry; the SDK does not verify payment. Contract replies omit email
994
+ and globally reusable credential data.
995
+
996
+ A removal receipt reports `session_cleanup: pending` until connection cleanup
997
+ is confirmed. Retry the same removal and version to confirm `complete`. These
998
+ APIs require the matching service feature and remain off by default during
999
+ integration. Consumer Noise enrollment and browser access are in the NHP agent.
@@ -1,5 +1,5 @@
1
1
  import { ShareLink } from "./share.js";
2
- import type { AccessCodeListOutput, ApiKey, ApiKeyListOutput, ApiKeyRequestScope, BillingInvoiceListOutput, BatchCreateInput, BatchCreateOutput, ClientOptions, ConnectorInstallation, ConnectorInstallationListOutput, CreateAccessCodeInput, CreateAccessCodeOutput, CreateApiKeyInput, CreateApiKeyOutput, CreateBillingCheckoutInput, CreateInput, CreateOutput, CreatePortalOptions, CreateQurlForResourceInput, CreateResourceInput, CreateWebhookInput, Customer, CheckoutSession, Domain, DomainListOutput, DomainVerifyResult, ExtendInput, Invoice, ListInput, ListOutput, ListApiKeysInput, ListBillingInvoicesInput, ListConnectorInstallationsInput, ListDomainsInput, ListWebhookDeliveriesInput, ListWebhooksInput, MintInput, MintOutput, Portal, PortalSession, ProtectUrlOptions, QURL, QurlSummary, Quota, RedeemAccessCodeInput, RedeemAccessCodeOutput, RegisterDomainInput, Resource, ResourceDetail, ResourceHandle, ResourceListInput, ResourceListOutput, RequestOptions, ResolveInput, ResolveOutput, SessionListOutput, SessionTerminateOutput, ShareResourceOptions, UpdateApiKeyInput, UpdateCustomerInput, UpdateInput, UpdateResourceInput, UpdateResourceQurlInput, UpdateWebhookInput, UsageCurrentPeriod, UsageDaily, Webhook, WebhookDelivery, WebhookDeliveryListOutput, WebhookEventTypeInfo, WebhookListOutput, WebhookWithSecret } from "./types.js";
2
+ import type { ConsumerAccessPolicy, ConsumerInvitation, ConsumerGrant, ConsumerGrantApprovalInput, ConsumerListInput, ConsumerInvitationListOutput, ConsumerGrantListOutput, AccessCodeListOutput, ApiKey, ApiKeyListOutput, ApiKeyRequestScope, BillingInvoiceListOutput, BatchCreateInput, BatchCreateOutput, ClientOptions, ConnectorInstallation, ConnectorInstallationListOutput, CreateAccessCodeInput, CreateAccessCodeOutput, CreateApiKeyInput, CreateApiKeyOutput, CreateBillingCheckoutInput, CreateDelegatedQurlBatchInput, CreateDelegatedQurlBatchOptions, CreateInput, CreateOutput, CreatePortalOptions, CreateQurlForResourceInput, CreateResourceInput, CreateWebhookInput, Customer, CheckoutSession, Domain, DomainListOutput, DomainVerifyResult, DelegatedQurl, DelegatedQurlBatchAccepted, GetDelegatedQurlBatchOptions, GetDelegatedQurlBatchOutput, ExtendInput, Invoice, ListInput, ListOutput, ListApiKeysInput, ListBillingInvoicesInput, ListConnectorInstallationsInput, ListDomainsInput, ListWebhookDeliveriesInput, ListWebhooksInput, MintInput, MintOutput, Portal, PortalSession, ProtectUrlOptions, QURL, QurlSummary, Quota, RedeemAccessCodeInput, RedeemAccessCodeOutput, RegisterDomainInput, Resource, ResourceDetail, ResourceHandle, ResourceListInput, ResourceListOutput, RequestOptions, ResolveInput, ResolveOutput, SessionListOutput, SessionTerminateOutput, ShareResourceOptions, UpdateApiKeyInput, UpdateCustomerInput, UpdateInput, UpdateResourceInput, UpdateResourceQurlInput, UpdateWebhookInput, UsageCurrentPeriod, UsageDaily, Webhook, WebhookDelivery, WebhookDeliveryListOutput, WebhookEventTypeInfo, WebhookListOutput, WebhookWithSecret } from "./types.js";
3
3
  /** Narrow a response scope before reusing it in a create/update request. */
4
4
  export declare function isApiKeyRequestScope(scope: string): scope is ApiKeyRequestScope;
5
5
  /**
@@ -96,7 +96,7 @@ export declare class QURLClient {
96
96
  */
97
97
  resourceByCrid(id: string): ProtectedResource;
98
98
  /** Find or create the active qURL Connector resource for an immutable slug. */
99
- ensureConnectorResource(slug: string, requestOptions?: RequestOptions): Promise<EnsureConnectorResourceResult>;
99
+ ensureConnectorResource(slug: string, requestOptions?: RequestOptions, consumerAccess?: ConsumerAccessPolicy): Promise<EnsureConnectorResourceResult>;
100
100
  /** Fetch a qURL Connector resource by its CRID. */
101
101
  getConnectorResource(crid: string): Promise<ConnectorResource>;
102
102
  /** Fetch the single active qURL Connector resource for an immutable slug. */
@@ -226,6 +226,24 @@ export declare class QURLClient {
226
226
  * ```
227
227
  */
228
228
  batchCreate(input: BatchCreateInput, options?: RequestOptions): Promise<BatchCreateOutput>;
229
+ /**
230
+ * Start one durable delegated qURL batch. The SDK sends this mutation once.
231
+ * If the result may have committed, retry explicitly with the same key and
232
+ * semantic body.
233
+ */
234
+ createDelegatedQurlBatch(input: CreateDelegatedQurlBatchInput, options: CreateDelegatedQurlBatchOptions): Promise<DelegatedQurlBatchAccepted>;
235
+ /**
236
+ * Read one delegated qURL batch state. One call performs one logical read;
237
+ * callers retain control of the poll count and total deadline.
238
+ */
239
+ getDelegatedQurlBatch(batchId: string, options?: GetDelegatedQurlBatchOptions): Promise<GetDelegatedQurlBatchOutput>;
240
+ /** Read owner-visible metadata for one delegated qURL. */
241
+ getDelegatedQurl(qurlId: string): Promise<DelegatedQurl>;
242
+ /**
243
+ * Revoke one delegated qURL. DELETE is never retried automatically. A 503
244
+ * `mutation_outcome_unknown` is safe to retry with the same qURL ID.
245
+ */
246
+ deleteDelegatedQurl(qurlId: string): Promise<void>;
229
247
  /**
230
248
  * Get a qURL resource and its access tokens.
231
249
  *
@@ -340,6 +358,22 @@ export declare class QURLClient {
340
358
  getResource(id: string): Promise<ResourceDetail>;
341
359
  /** Update resource metadata. */
342
360
  updateResource(id: string, input: UpdateResourceInput, options?: RequestOptions): Promise<Resource>;
361
+ /** Send a publisher-only invitation. Mail delivery does not prove enrollment. */
362
+ inviteConsumer(id: string, email: string): Promise<ConsumerInvitation>;
363
+ listConsumerInvitations(id: string, input?: ConsumerListInput): Promise<ConsumerInvitationListOutput>;
364
+ listConsumerGrants(id: string, input?: ConsumerListInput): Promise<ConsumerGrantListOutput>;
365
+ resendConsumerInvitation(id: string, invitationId: string, expectedVersion: number): Promise<ConsumerInvitation>;
366
+ /** Remove the invitation and its grant. Inspect session_cleanup before reporting stream removal. */
367
+ revokeConsumerInvitation(id: string, invitationId: string, expectedVersion: number): Promise<ConsumerInvitation>;
368
+ /** Review approval, key opt-in with grantId new, or trusted publisher entitlement. */
369
+ approveConsumerGrant(id: string, grantId: string, input: ConsumerGrantApprovalInput): Promise<ConsumerGrant>;
370
+ denyConsumerGrant(id: string, grantId: string, expectedVersion: number): Promise<ConsumerGrant>;
371
+ revokeConsumerGrant(id: string, grantId: string, expectedVersion: number): Promise<ConsumerGrant>;
372
+ /**
373
+ * Revoke an API resource identifier retained by a client migrating to CRIDs.
374
+ * New callers should use deleteResource with the resource CRID.
375
+ */
376
+ deleteResourceByIdentifier(id: string): Promise<void>;
343
377
  /** Revoke a resource and all of its qURLs. */
344
378
  deleteResource(id: string): Promise<void>;
345
379
  /**
@@ -359,15 +393,13 @@ export declare class QURLClient {
359
393
  revokeResourceQurl(id: string, qurlId: string): Promise<void>;
360
394
  /** Update a specific qURL token on a resource. */
361
395
  updateResourceQurl(id: string, qurlId: string, input: UpdateResourceQurlInput, options?: RequestOptions): Promise<QurlSummary>;
396
+ /** List every active session, following bounded service pages. */
397
+ listResourceSessions(id: string): Promise<SessionListOutput>;
362
398
  /**
363
- * List active access sessions for a resource.
364
- *
365
- * The current API contract has no cursor query params for this endpoint.
366
- * If the service later advertises pagination metadata, the SDK returns
367
- * this page and emits a debug log rather than pretending it fetched all pages.
399
+ * End every session page. This is not atomic: a failed page throws after earlier
400
+ * pages may have closed sessions. List sessions to reconcile, then retry the call.
401
+ * A retry can close newly admitted sessions and counts only its own transitions.
368
402
  */
369
- listResourceSessions(id: string): Promise<SessionListOutput>;
370
- /** Terminate all active sessions for a resource and return the server count. */
371
403
  terminateAllResourceSessions(id: string): Promise<SessionTerminateOutput>;
372
404
  /** Terminate a specific resource session. */
373
405
  terminateResourceSession(id: string, sessionId: string): Promise<void>;