gdc-sdk-node-ts 2.4.40 → 2.4.41

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.
@@ -2,6 +2,7 @@ import type { JWK } from 'gdc-common-utils-ts/models/jwk';
2
2
  import type { ActorKind } from 'gdc-common-utils-ts/models/actor-session';
3
3
  import type { LegalOrganizationVerificationTransactionInput } from 'gdc-common-utils-ts/utils/legal-organization-verification-transaction';
4
4
  import { type AppInfo, type ConfidentialStorageProfile, type PollOptions, type SubmitAndPollResult } from 'gdc-sdk-core-ts';
5
+ import { OrganizationControllerSdk } from './orchestration/organization-controller-sdk.js';
5
6
  import type { RouteContext } from './individual-onboarding.js';
6
7
  import type { HostRouteContext } from './host-onboarding.js';
7
8
  import type { SecureDidcommTransportAdapter } from 'gdc-sdk-core-ts';
@@ -205,6 +206,28 @@ export type ResolvedServerProfileSession = Readonly<{
205
206
  }>): Promise<unknown>;
206
207
  }>;
207
208
  }>;
209
+ /**
210
+ * Server-only authorization material used to reopen one registered controller.
211
+ *
212
+ * A product may let this manager open the PIN-protected seed directly, or may
213
+ * pass the same seed after its own passkey/session policy has authorized and
214
+ * unsealed it. `authorizedWalletSeed` must never cross a browser/API boundary.
215
+ */
216
+ export type ServerOrganizationControllerOpenInput = Readonly<{
217
+ ownerId: string;
218
+ profileId: string;
219
+ /** Fresh signed OIDC id_token used as the HTTP bearer for this operation. */
220
+ idToken: string;
221
+ /** User-entered or product-managed profile PIN; mutually exclusive with authorizedWalletSeed. */
222
+ pin?: string;
223
+ /** Already-authorized server-only 32-byte base64url seed; mutually exclusive with pin. */
224
+ authorizedWalletSeed?: string;
225
+ }>;
226
+ /** High-level controller facade plus its immutable durable profile metadata. */
227
+ export type OpenedServerOrganizationController = Readonly<{
228
+ profile: ServerProfileRecord;
229
+ sdk: OrganizationControllerSdk;
230
+ }>;
208
231
  export type ServerProfileSessionManagerOptions = Readonly<{
209
232
  store: ServerProfileStore;
210
233
  sealer: ServerProfileSealer;
@@ -275,6 +298,15 @@ export declare class ServerProfileSessionManager {
275
298
  */
276
299
  refreshSession(ownerId: string, sessionId: string, idToken: string): Promise<ResolvedServerProfileSession>;
277
300
  resolveSession(ownerId: string, sessionId: string): Promise<ResolvedServerProfileSession>;
301
+ /**
302
+ * Opens the high-level organization-controller API without exposing wallet,
303
+ * DIDComm, DCR or HTTP-client plumbing to the integrating BFF.
304
+ *
305
+ * The durable profile remains authoritative for actor DID, provider DID,
306
+ * route and DCR client id. The reconstructed keys must match the public keys
307
+ * registered for that profile before any gateway request can be sent.
308
+ */
309
+ openOrganizationController(input: ServerOrganizationControllerOpenInput): Promise<OpenedServerOrganizationController>;
278
310
  lock(ownerId: string, sessionId: string): Promise<void>;
279
311
  private createClient;
280
312
  private createWallet;
@@ -6,6 +6,7 @@ import { addLegalRepresentativeCredential, addOrganizationCredential, addService
6
6
  import { TransportProfiles, } from 'gdc-sdk-core-ts';
7
7
  import { NodeManagedWallet } from './node-managed-wallet.js';
8
8
  import { NodeHttpClient } from './node-runtime-client.js';
9
+ import { OrganizationControllerSdk } from './orchestration/organization-controller-sdk.js';
9
10
  import { buildIdentityOpenIdSmartTokenPath } from './runtime-paths.js';
10
11
  import { createProfileDeviceActivationRequest } from './device-activation.js';
11
12
  import { ProfilePinRejectedError, openServerProfileSecret, protectServerProfileSecret, } from './server-profile-protection.js';
@@ -408,6 +409,50 @@ export class ServerProfileSessionManager {
408
409
  },
409
410
  };
410
411
  }
412
+ /**
413
+ * Opens the high-level organization-controller API without exposing wallet,
414
+ * DIDComm, DCR or HTTP-client plumbing to the integrating BFF.
415
+ *
416
+ * The durable profile remains authoritative for actor DID, provider DID,
417
+ * route and DCR client id. The reconstructed keys must match the public keys
418
+ * registered for that profile before any gateway request can be sent.
419
+ */
420
+ async openOrganizationController(input) {
421
+ const profile = await this.requireOwnedProfile(input.ownerId, input.profileId);
422
+ if (profile.actorKind !== ActorKinds.OrganizationController || profile.actorMode !== 'controller') {
423
+ throw new Error('Profile is not an organization controller.');
424
+ }
425
+ const idToken = String(input.idToken || '').trim();
426
+ if (!idToken)
427
+ throw new Error('Opening an organization controller requires a signed OIDC idToken.');
428
+ const hasPin = Boolean(String(input.pin || '').trim());
429
+ const hasAuthorizedSeed = Boolean(String(input.authorizedWalletSeed || '').trim());
430
+ if (hasPin === hasAuthorizedSeed) {
431
+ throw new Error('Opening an organization controller requires exactly one of pin or authorizedWalletSeed.');
432
+ }
433
+ const seed = hasAuthorizedSeed
434
+ ? String(input.authorizedWalletSeed)
435
+ : await openServerProfileSecret(profile.protectedWalletSeed, String(input.pin), `${profile.profileId}:wallet-seed`, this.options.sealer);
436
+ requireBase64UrlSeed32(seed);
437
+ const walletKeyDerivationId = normalizedWalletKeyDerivationId(profile.walletKeyDerivationId, profile.profileId);
438
+ const wallet = await this.createWallet(walletKeyDerivationId, seed);
439
+ const context = walletContext(walletKeyDerivationId);
440
+ await requireRegisteredProfileKeys(wallet, context, profile);
441
+ const secureTransportAdapter = {
442
+ pack: (message) => wallet.packForRecipientWithContext(bindOrganizationControllerTransport(message, profile), profile.providerDid, { context }),
443
+ unpack: async (jwe) => (await wallet.unpackWithContext(jwe, { context })).content,
444
+ };
445
+ const client = new NodeHttpClient({
446
+ baseUrl: this.options.gatewayBaseUrl,
447
+ ctx: profile.routeContext,
448
+ bearerToken: idToken,
449
+ fetchImpl: this.options.fetchImpl,
450
+ appInfo: this.options.appInfo,
451
+ transportProfile: TransportProfiles.DidcommEncryptedForm,
452
+ secureTransportAdapter,
453
+ });
454
+ return { profile, sdk: new OrganizationControllerSdk(client) };
455
+ }
411
456
  async lock(ownerId, sessionId) {
412
457
  const session = await this.options.store.getSession(sessionId);
413
458
  if (session?.ownerId === ownerId)
@@ -489,6 +534,29 @@ export class ServerProfileSessionManager {
489
534
  function bindTransportActor(message, actorDid, clientId) {
490
535
  return { ...message, iss: actorDid, client_id: clientId };
491
536
  }
537
+ /** Binds the encrypted request to the immutable controller registration. */
538
+ function bindOrganizationControllerTransport(message, profile) {
539
+ return {
540
+ ...message,
541
+ iss: profile.actorDid,
542
+ aud: profile.providerDid,
543
+ client_id: profile.clientId,
544
+ };
545
+ }
546
+ /** Refuses a wrong or rotated seed before it can produce network traffic. */
547
+ async function requireRegisteredProfileKeys(wallet, context, profile) {
548
+ const derived = await wallet.getPublicJwks(context, {});
549
+ const derivedKids = new Set(derived.map((entry) => String(entry.kid || '').trim()).filter(Boolean));
550
+ const registeredKids = profile.publicJwks
551
+ .map((jwk) => String(jwk.kid || '').trim())
552
+ .filter(Boolean);
553
+ if (!registeredKids.length || registeredKids.some((kid) => !derivedKids.has(kid))) {
554
+ throw new Error('Authorized wallet seed does not match registered profile keys.');
555
+ }
556
+ if (profile.clientInstanceId && !derivedKids.has(profile.clientInstanceId)) {
557
+ throw new Error('Authorized wallet seed does not match the registered client instance.');
558
+ }
559
+ }
492
560
  /** Keeps the OpenID proof class aligned with the durable actor profile. */
493
561
  function profileSmartAcrValues(actorKind) {
494
562
  return actorKind === ActorKinds.IndividualController
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.4.40",
3
+ "version": "2.4.41",
4
4
  "description": "Next-generation Node runtime package for the GDC SDK family",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Antifraud Services Inc.",