{"version":3,"file":"index.mjs","names":[],"sources":["../../src/did.ts","../../src/invitations.ts","../../src/seedphrase.ts","../../src/passcode.ts","../../src/credentials/signing.ts","../../src/presentations/signing.ts","../../src/credentials/assertions.ts","../../src/credentials/verifier.ts","../../src/credentials/credential-factory.ts","../../src/credentials/credential-generator.ts","../../src/presentations/presentation.ts","../../src/presentations/verifier.ts","../../src/state-machine/feed-state-machine.ts","../../src/state-machine/invitation-state-machine.ts","../../src/graph/credential-graph.ts","../../src/state-machine/member-state-machine.ts","../../src/state-machine/space-state-machine.ts","../../src/processor/device-state-machine.ts","../../src/processor/profile-state-machine.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { subtleCrypto } from '@dxos/crypto';\nimport { IdentityDid, PublicKey } from '@dxos/keys';\nimport { ComplexMap } from '@dxos/util';\n\nconst IDENTITY_DIDS_CACHE = new ComplexMap<PublicKey, IdentityDid>(PublicKey.hash);\n\n/**\n * Identity DIDs are generated by creating a keypair, and then taking the first 20 bytes of the SHA-256 hash of the public key and encoding them to multibase RFC4648 base-32 format (prefixed with B, see Multibase Table).\n * Inspired by how ethereum addresses are derived.\n */\nexport const createDidFromIdentityKey = async (identityKey: PublicKey): Promise<IdentityDid> => {\n  const cachedValue = IDENTITY_DIDS_CACHE.get(identityKey);\n  if (cachedValue !== undefined) {\n    return cachedValue;\n  }\n\n  const digest = await subtleCrypto.digest('SHA-256', identityKey.asUint8Array() as Uint8Array<ArrayBuffer>);\n\n  const bytes = new Uint8Array(digest).slice(0, IdentityDid.byteLength);\n  const identityDid = IdentityDid.encode(bytes);\n  IDENTITY_DIDS_CACHE.set(identityKey, identityDid);\n  return identityDid;\n};\n","//\n// Copyright 2019 DXOS.org\n//\n\n/**\n * Info required for offline invitations.\n */\n// TODO(burdon): Define types.\nexport interface SecretInfo {\n  id: any;\n  authNonce: any;\n}\n\n/**\n * Provides a shared secret during an invitation process.\n */\nexport type SecretProvider = (info?: SecretInfo) => Promise<Buffer>;\n\n/**\n * Validates the shared secret during an invitation process.\n */\nexport type SecretValidator = (invitation: never, secret: Buffer) => Promise<boolean>;\n\nexport const defaultSecretProvider: SecretProvider = async () => Buffer.from('0000');\n\nexport const defaultSecretValidator: SecretValidator = async (invitation, secret) => true;\n","//\n// Copyright 2020 DXOS.org\n//\n\nimport { generateMnemonic, mnemonicToSeedSync } from 'bip39';\n\nimport { createKeyPair } from '@dxos/crypto';\nimport { invariant } from '@dxos/invariant';\nimport { type KeyPair } from '@dxos/keys';\n\n/**\n * Generate bip39 seed phrase (aka mnemonic).\n */\nexport const generateSeedPhrase = (): string => generateMnemonic();\n\n/**\n * Generate key pair from seed phrase.\n */\nexport const keyPairFromSeedPhrase = (seedPhrase: string): KeyPair => {\n  invariant(seedPhrase);\n  const seed = mnemonicToSeedSync(seedPhrase);\n  return createKeyPair(seed);\n};\n","//\n// Copyright 2019 DXOS.org\n//\n\n/**\n * Generates a numeric passcode.\n * @param {number} length\n * @returns {string}\n */\nexport const generatePasscode = (length = 4) => {\n  let passcode = '';\n  for (let i = 0; i < length; i++) {\n    passcode += `${Math.floor(Math.random() * 10)}`;\n  }\n\n  return passcode;\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport stableStringify from 'json-stable-stringify';\n\nimport { PublicKey } from '@dxos/keys';\nimport { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { Timeframe } from '@dxos/timeframe';\nimport { arrayToBuffer } from '@dxos/util';\n\n/**\n * @returns The input message to be signed for a given credential.\n */\n// TODO(nf): rename, this returns not the proof itself, but the payload for verifying against the proof.\nexport const getCredentialProofPayload = (credential: Credential): Uint8Array => {\n  const copy = {\n    ...credential,\n    proof: {\n      ...credential.proof,\n      value: new Uint8Array(),\n      chain: undefined,\n    },\n  };\n  if (copy.parentCredentialIds?.length === 0) {\n    delete copy.parentCredentialIds;\n  }\n  delete copy.id; // ID is not part of the signature payload.\n\n  // Normalize proto3-default values in the assertion to avoid serialization asymmetry.\n  // Proto3 omits fields equal to their default on the wire (empty arrays, 0, \"\", false),\n  // and our codec doesn't restore defaults on decode — so after a round-trip the field\n  // is absent. The signing payload must pre-strip these defaults (plus `null`/`undefined`,\n  // which the canonical stringify replacer also drops) so signer and verifier produce the\n  // same canonical bytes regardless of whether the field was explicitly set to its default.\n  // Clone subject + assertion so we don't mutate the caller's credential.\n  const originalAssertion = copy.subject?.assertion;\n  if (originalAssertion) {\n    const normalizedAssertion: Record<string, any> = { ...originalAssertion };\n    for (const key of Object.keys(normalizedAssertion)) {\n      const val = normalizedAssertion[key];\n      if (\n        val === undefined ||\n        val === null ||\n        val === 0 ||\n        val === '' ||\n        val === false ||\n        (Array.isArray(val) && val.length === 0)\n      ) {\n        delete normalizedAssertion[key];\n      }\n    }\n    copy.subject = { ...copy.subject, assertion: normalizedAssertion as typeof originalAssertion };\n  }\n\n  return Buffer.from(canonicalStringify(copy));\n};\n\n/**\n * Utility method to produce stable output for signing/verifying.\n */\nexport const canonicalStringify = (obj: any): string =>\n  stableStringify(obj, {\n    /* The point of signing and verifying is not that the internal, private state of the objects be\n     * identical, but that the public contents can be verified not to have been altered. For that reason,\n     * really private fields (indicated by '__') are not included in the signature.\n     * This gives a mechanism for attaching other attributes to an object without breaking the signature.\n     * We also skip @type.\n     */\n    // TODO(dmaretskyi): Should we actually skip the @type field?\n    replacer: function (this: any, key: any, value: any) {\n      if (key.toString().startsWith('__') || key.toString() === '@type') {\n        return undefined;\n      }\n\n      if (value === null) {\n        return undefined;\n      }\n\n      // Value before .toJSON() is called.\n      const original = this[key];\n\n      if (value) {\n        if (PublicKey.isPublicKey(value)) {\n          return value.toHex();\n        }\n        if (Buffer.isBuffer(value)) {\n          return value.toString('hex');\n        }\n\n        if (value instanceof Uint8Array) {\n          return arrayToBuffer(value).toString('hex');\n        }\n        if (value.data && value.type === 'Buffer') {\n          return Buffer.from(value).toString('hex');\n        }\n        if (original instanceof Timeframe) {\n          // Uses old key truncation method (339d...9d66) to keep backwards compatibility.\n          return original.frames().reduce((frames: Record<string, number>, [key, seq]) => {\n            frames[truncateKey(key)] = seq;\n            return frames;\n          }, {});\n        }\n      }\n\n      return value;\n    },\n  }) as string;\n\n/**\n * Old key truncation method (339d...9d66) to keep backwards compatibility with credentials signed with old method\n */\nconst truncateKey = (key: PublicKey) => {\n  const str = key.toHex();\n  return `${str.substring(0, 4)}...${str.substring(str.length - 4)}`;\n};\n\n/**\n * export const truncateKey = (key: any, { length = 8, start }: TruncateKeyOptions = {}) => {\nconst str = String(key);\nif (str.length <= length) {\n  return str;\n}\n\nreturn start\n  ? `${str.slice(0, length)}...`\n  : `${str.substring(0, length / 2)}...${str.substring(str.length - length / 2)}`;\n};\n\n{\n\"04009285\": 20,\n\"0415004f\": 0,\n\"0415e6d7\": 9964,\n\"042a4fa9\": 8,\n\"0448e62f\": 3,\n\"04775053\": 257,\n\"04a6b603\": 97,\n\"04bc5c9d\": 198,\n\"04da9930\": 59,\n\"04df0449\": 676,\n\"04e122ae\": 5435,\n\"04ee588b\": 1703\n}\n\n */\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Credential, type Proof } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { canonicalStringify } from '../credentials/signing';\n\nexport const getPresentationProofPayload = (credentials: Credential[], proof: Proof): Uint8Array => {\n  const copy = {\n    credentials: credentials.map((credential) => removeEmptyParentCredentialIds(credential)),\n    proof: {\n      ...proof,\n      value: new Uint8Array(),\n      chain: undefined,\n    },\n  };\n\n  return Buffer.from(canonicalStringify(copy));\n};\n\nconst removeEmptyParentCredentialIds = (credential: Credential): Credential => {\n  const copy = {\n    ...credential,\n    proof: credential.proof\n      ? {\n          ...credential.proof,\n          chain: credential.proof.chain\n            ? { credential: removeEmptyParentCredentialIds(credential.proof.chain.credential) }\n            : undefined,\n        }\n      : undefined,\n  };\n  if (copy.parentCredentialIds?.length === 0) {\n    delete copy.parentCredentialIds;\n  }\n  return copy;\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { type PublicKey } from '@dxos/keys';\nimport { type TypedMessage, type TYPES } from '@dxos/protocols/proto';\nimport { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nexport const getCredentialAssertion = (credential: Credential): TypedMessage => credential.subject.assertion;\n\nexport const isValidAuthorizedDeviceCredential = (\n  credential: Credential,\n  identityKey: PublicKey,\n  deviceKey: PublicKey,\n): boolean => {\n  const assertion = getCredentialAssertion(credential);\n  return (\n    credential.subject.id.equals(deviceKey) &&\n    credential.issuer.equals(identityKey) &&\n    assertion['@type'] === 'dxos.halo.credentials.AuthorizedDevice' &&\n    assertion.identityKey.equals(identityKey) &&\n    assertion.deviceKey.equals(deviceKey)\n  );\n};\n\nexport type SpecificCredential<T> = Omit<Credential, 'subject'> & {\n  subject: Omit<Credential['subject'], 'assertion'> & { assertion: T };\n};\n\nexport const checkCredentialType = <K extends keyof TYPES>(\n  credential: Credential,\n  type: K,\n): credential is SpecificCredential<TYPES[K]> => credential.subject.assertion['@type'] === type;\n\nexport const credentialTypeFilter =\n  <K extends keyof TYPES>(type: K) =>\n  (credential: Credential): credential is SpecificCredential<TYPES[K]> =>\n    checkCredentialType(credential, type);\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { verifySignature } from '@dxos/crypto';\nimport { type PublicKey } from '@dxos/keys';\nimport { type Chain, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { isValidAuthorizedDeviceCredential } from './assertions';\nimport { getCredentialProofPayload } from './signing';\n\nexport const SIGNATURE_TYPE_ED25519 = 'ED25519Signature';\n\nexport type VerificationResult = { kind: 'pass' } | { kind: 'fail'; errors: string[] };\n\nexport const verifyCredential = async (credential: Credential): Promise<VerificationResult> => {\n  if (credential.parentCredentialIds?.length === 0) {\n    delete credential.parentCredentialIds;\n  }\n\n  if (!credential.issuer.equals(credential.proof!.signer)) {\n    if (!credential.proof!.chain) {\n      return {\n        kind: 'fail',\n        errors: ['Delegated credential is missing credential chain.'],\n      };\n    }\n\n    const result = await verifyChain(credential.proof!.chain, credential.issuer, credential.proof!.signer);\n    if (result.kind === 'fail') {\n      return result;\n    }\n  }\n\n  const result = await verifyCredentialSignature(credential);\n  if (result.kind === 'fail') {\n    return result;\n  }\n\n  return { kind: 'pass' };\n};\n\n/**\n * Verifies that the signature is valid and was made by the signer.\n * Does not validate other semantics (e.g. chains).\n */\nexport const verifyCredentialSignature = async (credential: Credential): Promise<VerificationResult> => {\n  if (credential.proof!.type !== SIGNATURE_TYPE_ED25519) {\n    return {\n      kind: 'fail',\n      errors: [`Invalid signature type: ${credential.proof!.type}`],\n    };\n  }\n\n  const signData = getCredentialProofPayload(credential);\n  if (!(await verifySignature(credential.proof!.signer, signData, credential.proof!.value))) {\n    return { kind: 'fail', errors: ['Invalid signature'] };\n  }\n\n  return { kind: 'pass' };\n};\n\n/**\n * Verifies that the signer has the delegated authority to create credentials on behalf of the issuer.\n */\nexport const verifyChain = async (\n  chain: Chain,\n  authority: PublicKey,\n  subject: PublicKey,\n): Promise<VerificationResult> => {\n  const result = await verifyCredential(chain.credential);\n  if (result.kind === 'fail') {\n    return result;\n  }\n\n  if (!isValidAuthorizedDeviceCredential(chain.credential, authority, subject)) {\n    return {\n      kind: 'fail',\n      errors: [`Invalid credential chain: invalid assertion for key: ${subject}`],\n    };\n  }\n\n  return { kind: 'pass' };\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { type Signer, subtleCrypto } from '@dxos/crypto';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { type TypedMessage } from '@dxos/protocols/proto';\nimport { type Chain, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { getCredentialProofPayload } from './signing';\nimport { SIGNATURE_TYPE_ED25519, verifyChain } from './verifier';\n\nexport type CreateCredentialSignerProps = {\n  subject: PublicKey;\n  assertion: TypedMessage;\n  nonce?: Uint8Array;\n  parentCredentialIds?: PublicKey[];\n};\n\nexport type CreateCredentialProps = {\n  signer: Signer;\n  issuer: PublicKey;\n  signingKey?: PublicKey;\n\n  // Provided only if signer is different from issuer.\n  chain?: Chain;\n\n  subject: PublicKey;\n  assertion: TypedMessage;\n  nonce?: Uint8Array;\n  parentCredentialIds?: PublicKey[];\n};\n\n/**\n * Construct a signed credential message.\n */\nexport const createCredential = async ({\n  signer,\n  issuer,\n  subject,\n  assertion,\n  signingKey,\n  chain,\n  nonce,\n  parentCredentialIds,\n}: CreateCredentialProps): Promise<Credential> => {\n  invariant(assertion['@type'], 'Invalid assertion.');\n  invariant(!!signingKey === !!chain, 'Chain must be provided if and only if the signing key differs from the issuer.');\n  if (chain) {\n    const result = await verifyChain(chain, issuer, signingKey!);\n    invariant(result.kind === 'pass', 'Invalid chain.');\n  }\n\n  // Create the credential with proof value and chain fields missing (for signature payload).\n  const credential: Credential = {\n    issuer,\n    issuanceDate: new Date(),\n    subject: {\n      id: subject,\n      assertion,\n    },\n    parentCredentialIds,\n    proof: {\n      type: SIGNATURE_TYPE_ED25519,\n      creationDate: new Date(),\n      signer: signingKey ?? issuer,\n      value: new Uint8Array(),\n      nonce,\n    },\n  };\n\n  // Set proof after creating signature.\n  const signedPayload = getCredentialProofPayload(credential);\n  credential.proof!.value = await signer.sign(signingKey ?? issuer, signedPayload);\n  if (chain) {\n    credential.proof!.chain = chain;\n  }\n\n  credential.id = PublicKey.from(await subtleCrypto.digest('SHA-256', signedPayload as Uint8Array<ArrayBuffer>));\n\n  return credential;\n};\n\n// TODO(burdon): Use consistently (merge halo/echo protocol packages).\nexport const createCredentialMessage = (credential: Credential) => {\n  return {\n    '@type': 'dxos.echo.feed.CredentialsMessage',\n    credential,\n  };\n};\n\n// TODO(burdon): Vs. Signer.\nexport interface CredentialSigner {\n  getIssuer(): PublicKey;\n  createCredential: (params: CreateCredentialSignerProps) => Promise<Credential>;\n}\n\n/**\n * Issue credentials directly signed by the issuer.\n */\nexport const createCredentialSignerWithKey = (signer: Signer, issuer: PublicKey): CredentialSigner => ({\n  getIssuer: () => issuer,\n  createCredential: ({ subject, assertion, nonce, parentCredentialIds }) =>\n    createCredential({\n      signer,\n      issuer,\n      subject,\n      assertion,\n      nonce,\n      parentCredentialIds,\n    }),\n});\n\n/**\n * Issue credentials with transitive proof via a chain.\n */\nexport const createCredentialSignerWithChain = (\n  signer: Signer,\n  chain: Chain,\n  signingKey: PublicKey,\n): CredentialSigner => ({\n  getIssuer: () => chain.credential.issuer,\n  createCredential: ({ subject, assertion, nonce, parentCredentialIds }) =>\n    createCredential({\n      signer,\n      issuer: chain.credential.issuer,\n      signingKey,\n      chain,\n      subject,\n      assertion,\n      nonce,\n      parentCredentialIds,\n    }),\n});\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { type Signer } from '@dxos/crypto';\nimport { type PublicKey } from '@dxos/keys';\nimport { type TypedMessage } from '@dxos/protocols/proto';\nimport { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';\nimport {\n  AdmittedFeed,\n  type Credential,\n  type DeviceProfileDocument,\n  MembershipPolicy,\n  type ProfileDocument,\n  SpaceMember,\n} from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';\nimport { Timeframe } from '@dxos/timeframe';\n\nimport { type CredentialSigner, createCredential } from './credential-factory';\n\n// TODO(burdon): Normalize generate and functions below.\n//  Use throughout stack and in tests.\n\n/**\n * Utility class for generating credential messages, where the issuer is the current identity or device.\n */\nexport class CredentialGenerator {\n  constructor(\n    private readonly _signer: Signer,\n    private readonly _identityKey: PublicKey,\n    private readonly _deviceKey: PublicKey,\n  ) {}\n\n  /**\n   * Create genesis messages for new Space.\n   */\n  async createSpaceGenesis(\n    spaceKey: PublicKey,\n    controlKey: PublicKey,\n    creatorProfile?: ProfileDocument,\n    membershipPolicy: MembershipPolicy = MembershipPolicy.INVITE,\n  ): Promise<Credential[]> {\n    return [\n      await createCredential({\n        signer: this._signer,\n        issuer: spaceKey,\n        subject: spaceKey,\n        assertion: {\n          '@type': 'dxos.halo.credentials.SpaceGenesis',\n          spaceKey,\n          membershipPolicy,\n        },\n      }),\n\n      await createCredential({\n        signer: this._signer,\n        issuer: spaceKey,\n        subject: this._identityKey,\n        assertion: {\n          '@type': 'dxos.halo.credentials.SpaceMember',\n          spaceKey,\n          'role': SpaceMember.Role.ADMIN,\n          'profile': creatorProfile,\n          'genesisFeedKey': controlKey,\n        },\n      }),\n\n      await this.createFeedAdmission(spaceKey, controlKey, AdmittedFeed.Designation.CONTROL),\n    ];\n  }\n\n  /**\n   * Create invitation.\n   * Admit identity and control and data feeds.\n   */\n  // TODO(burdon): Reconcile with above (esp. Signer).\n  async createMemberInvitation(\n    spaceKey: PublicKey,\n    identityKey: PublicKey,\n    deviceKey: PublicKey,\n    controlKey: PublicKey,\n    dataKey: PublicKey,\n    genesisFeedKey: PublicKey,\n  ): Promise<Credential[]> {\n    return [\n      await createCredential({\n        signer: this._signer,\n        issuer: this._identityKey,\n        subject: identityKey,\n        assertion: {\n          '@type': 'dxos.halo.credentials.SpaceMember',\n          spaceKey,\n          'role': SpaceMember.Role.EDITOR,\n          genesisFeedKey,\n        },\n      }),\n\n      await this.createFeedAdmission(spaceKey, controlKey, AdmittedFeed.Designation.CONTROL),\n      await this.createFeedAdmission(spaceKey, dataKey, AdmittedFeed.Designation.DATA),\n    ];\n  }\n\n  /**\n   * Add device to space.\n   */\n  // TODO(burdon): Reconcile with below.\n  async createDeviceAuthorization(deviceKey: PublicKey): Promise<Credential> {\n    return createCredential({\n      signer: this._signer,\n      issuer: this._identityKey,\n      subject: deviceKey,\n      assertion: {\n        '@type': 'dxos.halo.credentials.AuthorizedDevice',\n        'identityKey': this._identityKey,\n        deviceKey,\n      },\n    });\n  }\n\n  /**\n   * Add device metadata.\n   */\n  async createDeviceProfile(profile: DeviceProfileDocument): Promise<Credential> {\n    return createCredential({\n      signer: this._signer,\n      issuer: this._identityKey,\n      subject: this._deviceKey,\n      assertion: {\n        '@type': 'dxos.halo.credentials.DeviceProfile',\n        profile,\n      },\n    });\n  }\n\n  /**\n   * Add feed to space.\n   */\n  async createFeedAdmission(\n    spaceKey: PublicKey,\n    feedKey: PublicKey,\n    designation: AdmittedFeed.Designation,\n  ): Promise<Credential> {\n    return createCredential({\n      signer: this._signer,\n      issuer: this._identityKey,\n      subject: feedKey,\n      assertion: {\n        '@type': 'dxos.halo.credentials.AdmittedFeed',\n        spaceKey,\n        'identityKey': this._identityKey,\n        'deviceKey': this._deviceKey,\n        designation,\n      },\n    });\n  }\n\n  async createProfileCredential(profile: ProfileDocument): Promise<Credential> {\n    return createCredential({\n      signer: this._signer,\n      issuer: this._identityKey,\n      subject: this._identityKey,\n      assertion: {\n        '@type': 'dxos.halo.credentials.IdentityProfile',\n        profile,\n      },\n    });\n  }\n\n  async createEpochCredential(spaceKey: PublicKey): Promise<Credential> {\n    return createCredential({\n      signer: this._signer,\n      issuer: this._identityKey,\n      subject: spaceKey,\n      assertion: {\n        '@type': 'dxos.halo.credentials.Epoch',\n        'number': 0,\n        'timeframe': new Timeframe(),\n      },\n    });\n  }\n}\n\n// TODO(burdon): Reconcile with above (esp. Signer).\nexport const createDeviceAuthorization = async (\n  signer: CredentialSigner,\n  identityKey: PublicKey,\n  deviceKey: PublicKey,\n): Promise<TypedMessage[]> => {\n  const credentials = await Promise.all([\n    await signer.createCredential({\n      subject: deviceKey,\n      assertion: {\n        '@type': 'dxos.halo.credentials.AuthorizedDevice',\n        identityKey,\n        deviceKey,\n      },\n    }),\n  ]);\n\n  return credentials.map((credential) => ({\n    '@type': 'dxos.echo.feed.CredentialsMessage',\n    credential,\n  }));\n};\n\n// TODO(burdon): Reconcile with above (esp. Signer).\n/**\n * @param signer - invitation signer.\n * @param identityKey - identity key of the admitted member.\n * @param spaceKey - subject space key.\n * @param genesisFeedKey - genesis feed key of the space.\n * @param role - role of the newly added member.\n * @param membershipChainHeads - ids of the last known SpaceMember credentials (branching possible).\n * @param profile - profile of the newly added member.\n * @param invitationCredentialId - id of the delegated invitation credential in case one was used to add the member.\n */\nexport const createAdmissionCredentials = async (\n  signer: CredentialSigner,\n  identityKey: PublicKey,\n  spaceKey: PublicKey,\n  genesisFeedKey: PublicKey,\n  role: SpaceMember.Role = SpaceMember.Role.ADMIN,\n  membershipChainHeads: PublicKey[] = [],\n  profile?: ProfileDocument,\n  invitationCredentialId?: PublicKey,\n  tags?: string[],\n): Promise<FeedMessage.Payload[]> => {\n  const credentials = await Promise.all([\n    await signer.createCredential({\n      subject: identityKey,\n      parentCredentialIds: membershipChainHeads,\n      assertion: {\n        '@type': 'dxos.halo.credentials.SpaceMember',\n        spaceKey,\n        role,\n        profile,\n        genesisFeedKey,\n        invitationCredentialId,\n        'tags': tags ?? [],\n      },\n    }),\n  ]);\n\n  return credentials.map((credential) => ({\n    credential: { credential },\n  }));\n};\n\nexport const createDelegatedSpaceInvitationCredential = async (\n  signer: CredentialSigner,\n  subject: PublicKey,\n  invitation: DelegateSpaceInvitation,\n): Promise<FeedMessage.Payload> => {\n  const credential = await signer.createCredential({\n    subject,\n    assertion: {\n      '@type': 'dxos.halo.invitations.DelegateSpaceInvitation',\n      'invitationId': invitation.invitationId,\n      'authMethod': invitation.authMethod,\n      'swarmKey': invitation.swarmKey,\n      'role': invitation.role,\n      'guestKey': invitation.guestKey,\n      'expiresOn': invitation.expiresOn,\n      'multiUse': invitation.multiUse,\n    },\n  });\n  return { credential: { credential } };\n};\n\n/**\n * @param signer - credential issuer.\n * @param subject - key of the space the invitation was for.\n * @param invitationCredentialId id of a dxos.halo.invitations.DelegateSpaceInvitation credential.\n */\nexport const createCancelDelegatedSpaceInvitationCredential = async (\n  signer: CredentialSigner,\n  subject: PublicKey,\n  invitationCredentialId: PublicKey,\n): Promise<FeedMessage.Payload> => {\n  const credential = await signer.createCredential({\n    subject,\n    assertion: {\n      '@type': 'dxos.halo.invitations.CancelDelegatedInvitation',\n      'credentialId': invitationCredentialId,\n    },\n  });\n  return { credential: { credential } };\n};\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport { type Signer } from '@dxos/crypto';\nimport { type PublicKey } from '@dxos/keys';\nimport { type Chain, type Presentation, type Proof } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { SIGNATURE_TYPE_ED25519 } from '../credentials';\nimport { getPresentationProofPayload } from './signing';\n\n// TODO(burdon): Rename createPresentation?\nexport const signPresentation = async ({\n  presentation,\n  signer,\n  signerKey,\n  chain,\n  nonce,\n}: {\n  presentation: Presentation;\n  signer: Signer;\n  signerKey: PublicKey;\n  chain?: Chain;\n  nonce?: Uint8Array;\n}): Promise<Presentation> => {\n  const proof: Proof = {\n    type: SIGNATURE_TYPE_ED25519,\n    value: new Uint8Array(),\n    creationDate: new Date(),\n    signer: signerKey,\n    nonce,\n  };\n\n  const signedPayload = getPresentationProofPayload(presentation.credentials ?? [], proof);\n  proof.value = await signer.sign(signerKey, signedPayload);\n  if (chain) {\n    proof.chain = chain;\n  }\n\n  return {\n    credentials: presentation.credentials,\n    proofs: [...(presentation.proofs ?? []), proof],\n  };\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { verifySignature } from '@dxos/crypto';\nimport { type Presentation, type Proof } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { SIGNATURE_TYPE_ED25519, type VerificationResult, verifyChain, verifyCredential } from '../credentials';\nimport { getPresentationProofPayload } from './signing';\n\nexport const verifyPresentation = async (presentation: Presentation): Promise<VerificationResult> => {\n  const errors: string[] = [];\n\n  // Verify all credentials.\n  const credentialsVerifications = await Promise.all(\n    presentation.credentials?.map((credential) => verifyCredential(credential)) ?? [],\n  );\n  for (const verification of credentialsVerifications) {\n    if (verification.kind === 'fail') {\n      errors.push(...verification.errors);\n    }\n  }\n\n  // Verify all proofs.\n  const proofVerification = await Promise.all(\n    presentation.proofs?.map(async (proof) => {\n      const chainVerification = await verifyPresentationChain(presentation, proof);\n      if (chainVerification.kind === 'fail') {\n        return chainVerification;\n      }\n      const signatureVerification = await verifyPresentationSignature(presentation, proof);\n      if (signatureVerification.kind === 'fail') {\n        return signatureVerification;\n      }\n      return { kind: 'pass' } as VerificationResult;\n    }) ?? [],\n  );\n  for (const verification of proofVerification) {\n    if (verification.kind === 'fail') {\n      errors.push(...verification.errors);\n    }\n  }\n\n  if (errors.length === 0) {\n    return { kind: 'pass' };\n  }\n  {\n    return {\n      kind: 'fail',\n      errors,\n    };\n  }\n};\n\nexport const verifyPresentationChain = async (\n  presentation: Presentation,\n  proof: Proof,\n): Promise<VerificationResult> => {\n  for (const credential of presentation.credentials ?? []) {\n    if (!credential.issuer.equals(proof.signer)) {\n      if (!proof.chain) {\n        return {\n          kind: 'fail',\n          errors: ['Delegated credential is missing credential chain.'],\n        };\n      }\n\n      const chainVerification = await verifyChain(proof.chain, credential.subject.id, proof.signer);\n      if (chainVerification.kind === 'fail') {\n        return chainVerification;\n      }\n    }\n  }\n\n  return { kind: 'pass' };\n};\n\n/**\n * Verifies that the signature is valid and was made by the signer.\n * Does not validate other semantics (e.g. chains).\n */\nexport const verifyPresentationSignature = async (\n  presentation: Presentation,\n  proof: Proof,\n): Promise<VerificationResult> => {\n  if (proof.type !== SIGNATURE_TYPE_ED25519) {\n    return {\n      kind: 'fail',\n      errors: [`Invalid signature type: ${proof.type}`],\n    };\n  }\n\n  const signData = getPresentationProofPayload(presentation.credentials ?? [], proof);\n  if (!(await verifySignature(proof.signer, signData, proof.value))) {\n    return { kind: 'fail', errors: ['Invalid signature'] };\n  }\n\n  return { kind: 'pass' };\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { type AdmittedFeed, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { type AsyncCallback, Callback, ComplexMap } from '@dxos/util';\n\nimport { getCredentialAssertion } from '../credentials';\n\nexport interface FeedInfo {\n  key: PublicKey;\n  /**\n   * Parent feed from the feed tree.\n   * This is the feed where the AdmittedFeed assertion is written.\n   * The genesis feed will have itself as a parent.\n   */\n  parent: PublicKey;\n  credential: Credential;\n  assertion: AdmittedFeed;\n}\n\n/**\n * Tracks the feed tree for a space.\n * Provides a list of admitted feeds.\n */\nexport class FeedStateMachine {\n  private _feeds = new ComplexMap<PublicKey, FeedInfo>(PublicKey.hash);\n\n  readonly onFeedAdmitted = new Callback<AsyncCallback<FeedInfo>>();\n\n  constructor(private readonly _spaceKey: PublicKey) {}\n\n  get feeds(): ReadonlyMap<PublicKey, FeedInfo> {\n    return this._feeds;\n  }\n\n  /**\n   * Processes the AdmittedFeed credential.\n   * Assumes the credential is already pre-verified\n   * and the issuer has been authorized to issue credentials of this type.\n   * @param fromFeed Key of the feed where this credential is recorded.\n   */\n  async process(credential: Credential, fromFeed: PublicKey): Promise<void> {\n    const assertion = getCredentialAssertion(credential);\n    invariant(assertion['@type'] === 'dxos.halo.credentials.AdmittedFeed');\n    invariant(assertion.spaceKey.equals(this._spaceKey));\n\n    const info: FeedInfo = {\n      key: credential.subject.id,\n      credential,\n      assertion,\n      parent: fromFeed,\n    };\n\n    this._feeds.set(credential.subject.id, info);\n    await this.onFeedAdmitted.callIfSet(info);\n  }\n}\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { PublicKey } from '@dxos/keys';\nimport { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';\nimport { type AsyncCallback, Callback, ComplexMap, ComplexSet } from '@dxos/util';\n\nimport { getCredentialAssertion } from '../credentials';\n\nexport interface DelegateInvitationCredential {\n  credentialId: PublicKey;\n  invitation: DelegateSpaceInvitation;\n}\n\n/**\n * Tracks the feed tree for a space.\n * Provides a list of admitted feeds.\n */\nexport class InvitationStateMachine {\n  private readonly _invitations = new ComplexMap<PublicKey, DelegateSpaceInvitation>(PublicKey.hash);\n  private readonly _redeemedInvitationCredentialIds = new ComplexSet(PublicKey.hash);\n  private readonly _cancelledInvitationCredentialIds = new ComplexSet(PublicKey.hash);\n\n  readonly onDelegatedInvitation = new Callback<AsyncCallback<DelegateInvitationCredential>>();\n  readonly onDelegatedInvitationRemoved = new Callback<AsyncCallback<DelegateInvitationCredential>>();\n\n  get invitations(): ReadonlyMap<PublicKey, DelegateSpaceInvitation> {\n    return this._invitations;\n  }\n\n  async process(credential: Credential): Promise<void> {\n    const credentialId = credential.id;\n    if (credentialId == null) {\n      return;\n    }\n    const assertion = getCredentialAssertion(credential);\n    switch (assertion['@type']) {\n      case 'dxos.halo.invitations.CancelDelegatedInvitation': {\n        this._cancelledInvitationCredentialIds.add(assertion.credentialId);\n        const existingInvitation = this._invitations.get(assertion.credentialId);\n        if (existingInvitation != null) {\n          this._invitations.delete(assertion.credentialId);\n          await this.onDelegatedInvitationRemoved.callIfSet({\n            credentialId: assertion.credentialId,\n            invitation: existingInvitation,\n          });\n        }\n        break;\n      }\n      case 'dxos.halo.invitations.DelegateSpaceInvitation': {\n        if (credential.id) {\n          const isExpired = assertion.expiresOn && assertion.expiresOn.getTime() < Date.now();\n          const wasUsed = this._redeemedInvitationCredentialIds.has(credential.id) && !assertion.multiUse;\n          const wasCancelled = this._cancelledInvitationCredentialIds.has(credential.id);\n          if (isExpired || wasCancelled || wasUsed) {\n            return;\n          }\n          const invitation: DelegateSpaceInvitation = { ...assertion };\n          this._invitations.set(credential.id, invitation);\n          await this.onDelegatedInvitation.callIfSet({\n            credentialId: credential.id,\n            invitation,\n          });\n        }\n        break;\n      }\n      case 'dxos.halo.credentials.SpaceMember': {\n        if (assertion.invitationCredentialId != null) {\n          this._redeemedInvitationCredentialIds.add(assertion.invitationCredentialId);\n          const existingInvitation = this._invitations.get(assertion.invitationCredentialId);\n          if (existingInvitation != null && !existingInvitation.multiUse) {\n            this._invitations.delete(assertion.invitationCredentialId);\n            await this.onDelegatedInvitationRemoved.callIfSet({\n              credentialId: assertion.invitationCredentialId,\n              invitation: existingInvitation,\n            });\n          }\n        }\n        break;\n      }\n    }\n  }\n}\n","//\n// Copyright 2024 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { type AsyncCallback, Callback, ComplexMap, ComplexSet } from '@dxos/util';\n\nexport class CredentialGraph<A, State> {\n  /**\n   * Local ids are used during traversals.\n   */\n  private _vertexIdGenerator = 1;\n  /**\n   * All credentials without parent references are connected to the root.\n   */\n  private _root = { id: -1, parents: [], children: [] } as any as ChainVertex<A>;\n  /**\n   * A credential which is not a parent of any other credential has the sentinel as a child.\n   * Sentinel is a virtual merge-point of all credentials.\n   */\n  private _sentinel = { id: -2, parents: [], children: [] } as any as ChainVertex<A>;\n  /**\n   * Vertex references are used for fast credential inserts into the graph.\n   */\n  private _vertexByCredentialId = new ComplexMap<PublicKey, ChainVertex<A>>(PublicKey.hash);\n  /**\n   * The current state of the graph.\n   */\n  private _subjectToVertex = new ComplexMap<PublicKey, ChainVertex<A>>(PublicKey.hash);\n  private _subjectToState = new ComplexMap<PublicKey, State>(PublicKey.hash);\n\n  public onSubjectStateChanged = new Callback<AsyncCallback<State[]>>();\n\n  constructor(private readonly _stateHandler: CredentialGraphStateHandler<A, State>) {}\n\n  public getSubjectState(subjectId: PublicKey): State | undefined {\n    return this._subjectToState.get(subjectId);\n  }\n\n  public getState(): ReadonlyMap<PublicKey, State> {\n    return this._subjectToState;\n  }\n\n  public getLeafIds(): PublicKey[] {\n    return this._sentinel.parents.map((v) => v.credential!.id!);\n  }\n\n  public getGlobalStateScope(): StateScope<A> {\n    return { state: this._subjectToVertex };\n  }\n\n  public addVertex(credential: Credential, assertion: A): Promise<void> {\n    const newVertex: ChainVertex<A> = {\n      id: this._vertexIdGenerator++,\n      credential,\n      assertion,\n      parents: [],\n      children: [],\n    };\n    this._vertexByCredentialId.set(credential.id!, newVertex);\n    const parentIds = credential.parentCredentialIds ?? [];\n    if (parentIds.length === 0) {\n      this._root.children.push(newVertex);\n      newVertex.parents.push(this._root);\n    } else {\n      for (const parentId of parentIds) {\n        const parentVertex = this._vertexByCredentialId.get(parentId);\n        if (parentVertex == null) {\n          log.error('credential skipped because of the unknown parent', { credential, parentId });\n          continue;\n        }\n        parentVertex.children.push(newVertex);\n        newVertex.parents.push(parentVertex);\n        this._removeSentinelConnection(parentVertex);\n      }\n    }\n    newVertex.children.push(this._sentinel);\n    this._sentinel.parents.push(newVertex);\n    return this._onVertexInserted(newVertex);\n  }\n\n  private _removeSentinelConnection(vertex: ChainVertex<A>): void {\n    const sentinelIdx = vertex.children.indexOf(this._sentinel);\n    if (sentinelIdx >= 0) {\n      vertex.children.splice(sentinelIdx, 1);\n      const vertexInSentinelIdx = this._sentinel.parents.indexOf(vertex);\n      invariant(vertexInSentinelIdx >= 0);\n      this._sentinel.parents.splice(vertexInSentinelIdx, 1);\n    }\n  }\n\n  private async _onVertexInserted(newVertex: ChainVertex<A>): Promise<void> {\n    const { credential, assertion } = newVertex;\n    invariant(credential);\n    let changedSubjects: State[] = [];\n    const isUpdateAppliedOnTopOfThePreviousState = this._sentinel.parents.length === 1;\n    if (isUpdateAppliedOnTopOfThePreviousState) {\n      const subjectId = credential.subject.id;\n      if (this._stateHandler.isUpdateAllowed(this.getGlobalStateScope(), credential, assertion)) {\n        const newSubjectState = this._stateHandler.createState(credential, newVertex.assertion);\n        const prevSubjectState = this._subjectToState.get(subjectId);\n        this._subjectToState.set(subjectId, newSubjectState);\n        this._subjectToVertex.set(subjectId, newVertex);\n        if (this._stateHandler.hasStateChanged(newSubjectState, prevSubjectState)) {\n          changedSubjects.push(newSubjectState);\n        }\n      }\n    } else {\n      changedSubjects = this._recomputeState();\n    }\n    if (changedSubjects.length > 0) {\n      await this.onSubjectStateChanged.callIfSet(changedSubjects);\n    }\n  }\n\n  /**\n   * DFS the graph from root to sentinel pausing on merge points (nodes with multiple parents).\n   * Continue after all paths leading to a merge point converge by merging their states.\n   * In case of a concurrent update paths are replayed taking into account the state set\n   * by the winning branch.\n   */\n  private _recomputeState(): State[] {\n    // ID of a merge point to the list of paths that reached the point.\n    const pendingPaths = new Map<number, PathState<A>[]>();\n    const paths: PathState<A>[] = [this._createRootPath()];\n    let lastPath: PathState<A> | null = null;\n    while (lastPath == null) {\n      const path = paths.pop()!;\n      log('visit vertex', { id: path.head.id });\n      this._updatePathState(path);\n      const convergedPaths = this._handleMergePoint(paths, pendingPaths, path);\n      if (convergedPaths == null) {\n        log('waiting for other paths');\n        continue;\n      }\n      const mergeResult = this._mergePaths(convergedPaths);\n      if (mergeResult.type === 'replay_required') {\n        this._replayFailedPaths(paths, pendingPaths, mergeResult, convergedPaths);\n        continue;\n      }\n      const merged = mergeResult.path;\n      if (merged.head.children.length === 0) {\n        lastPath = merged;\n      } else if (merged.head.children.length === 1) {\n        merged.head = merged.head.children[0];\n        paths.push(merged);\n      } else {\n        this._forkTraversal(paths, merged);\n      }\n    }\n    if (paths.length > 0) {\n      log.error('traversal finished while there were active paths', {\n        paths: paths.map((p) => ({ path: toChosenPath(p), head: p.head.id })),\n      });\n    }\n    return this._setCurrentState(lastPath);\n  }\n\n  private _replayFailedPaths(\n    paths: PathState<A>[],\n    pendingPaths: Map<number, PathState<A>[]>,\n    mergeResult: ReplayRequiredMergeResult<A>,\n    convergedPaths: PathState<A>[],\n  ): void {\n    paths.push(\n      ...mergeResult.replay.map((path) => {\n        const stateOverrides = path.stateOverrides ?? new ComplexMap<PublicKey, ChainVertex<A>>(PublicKey.hash);\n        mergeResult.stateOverrides.forEach((value, key) => stateOverrides.set(key, value));\n        return { ...mergeResult.from, chosenPath: path.chosenPath, stateOverrides };\n      }),\n    );\n    log('replay paths', () => ({\n      count: paths.length,\n      paths: paths.map((path) => ({\n        from: mergeResult.from.head.id,\n        path: toChosenPath(path),\n        overrides: path?.stateOverrides?.mapValues((v) => this._stateHandler.toLogString(v.assertion)),\n      })),\n    }));\n    const clearedPending = convergedPaths.filter((l) => !mergeResult.replay.includes(l));\n    pendingPaths.set(convergedPaths[0].head.id, clearedPending);\n  }\n\n  private _handleMergePoint(\n    paths: PathState<A>[],\n    pendingPaths: Map<number, PathState<A>[]>,\n    path: PathState<A>,\n  ): PathState<A>[] | null {\n    const pendingList = pendingPaths.get(path.head.id) ?? [];\n    pendingPaths.set(path.head.id, pendingList);\n    pendingList.push(path);\n    if (pendingList.length < path.head.parents.length) {\n      return null;\n    }\n    if (path.head.id === this._sentinel.id && paths.length > 0) {\n      log('waiting for all the active paths to converge on the sentinel');\n      return null;\n    }\n    pendingPaths.delete(path.head.id);\n    return pendingList;\n  }\n\n  private _updatePathState(path: PathState<A>): void {\n    const headCredential = path.head.credential;\n    if (headCredential == null) {\n      return;\n    }\n    const updatedSubject = headCredential.subject.id;\n    path.credentials.add(headCredential.id!);\n    let isUpdateAllowed = this._stateHandler.isUpdateAllowed(path, headCredential, path.head.assertion);\n    // Compatibility with old credentials where parent references were not specified.\n    if (!isUpdateAllowed && path.head.parents[0]?.id === this._root.id) {\n      const globalState = this.getGlobalStateScope();\n      isUpdateAllowed = this._stateHandler.isUpdateAllowed(globalState, headCredential, path.head.assertion);\n    }\n    if (isUpdateAllowed) {\n      path.forkChangedSubjects.add(updatedSubject);\n      path.forkIssuers.add(headCredential.issuer);\n      path.state.set(updatedSubject, path.head);\n      log('path state updated', () => ({\n        subject: updatedSubject,\n        newState: this._stateHandler.toLogString(path.head.assertion),\n      }));\n    }\n  }\n\n  private _forkTraversal(paths: PathState<A>[], path: PathState<A>): void {\n    const replayChoice = path.chosenPath?.[path.head.id];\n    const choices = replayChoice ?? path.head.children;\n    for (const choice of choices) {\n      log('edge traversal', { from: path.head.id, to: choice.id });\n      const fork: PathState<A> = {\n        forkPoint: path,\n        chosenPath: { ...path.chosenPath, [path.head.id]: [choice] },\n        head: choice,\n        credentials: new ComplexSet(PublicKey.hash, path.credentials),\n        state: new ComplexMap(PublicKey.hash, [...path.state.entries()]),\n        forkIssuers: new ComplexSet(PublicKey.hash),\n        forkChangedSubjects: new ComplexSet(PublicKey.hash),\n        stateOverrides: path.stateOverrides,\n      };\n      paths.push(fork);\n    }\n  }\n\n  /**\n   * Updates the current graph state.\n   * @returns changed states.\n   */\n  private _setCurrentState(path: PathState<A>): State[] {\n    const changedSubjects: State[] = [];\n    const newStateMap = new ComplexMap<PublicKey, State>(PublicKey.hash);\n    const newVertexMap = new ComplexMap<PublicKey, ChainVertex<A>>(PublicKey.hash);\n    for (const [subjectKey, subjectVertex] of path.state.entries()) {\n      const newState = this._stateHandler.createState(subjectVertex.credential!, subjectVertex.assertion);\n      const prevState = this._subjectToState.get(subjectKey);\n      newStateMap.set(subjectKey, newState);\n      newVertexMap.set(subjectKey, subjectVertex);\n      if (this._stateHandler.hasStateChanged(newState, prevState)) {\n        changedSubjects.push(newState);\n      }\n    }\n    this._subjectToState = newStateMap;\n    this._subjectToVertex = newVertexMap;\n    return changedSubjects;\n  }\n\n  /*\n   * Walk up all the fork points and return the first one present in all the paths.\n   * We use local id to determine vertex position in the graph, because nodes can't\n   * be inserted in the middle (between a parent and a child) and ids are monotonically increasing.\n   */\n  private _leastCommonAncestor(paths: PathState<A>[]): PathState<A> {\n    const uniqueForkPoints = paths.reduce((acc, path) => {\n      let it = path.forkPoint;\n      while (it) {\n        acc.set(it.head.id, it);\n        it = it.forkPoint;\n      }\n      return acc;\n    }, new Map<number, PathState<A>>());\n    let maxId = this._root.id;\n    let maxState: PathState<A> | null = null;\n    for (const [id, state] of uniqueForkPoints.entries()) {\n      const headCredential = state.head.credential;\n      if (headCredential != null) {\n        const isPointInEveryPath = paths.every((p) => p.credentials.has(headCredential.id!));\n        if (isPointInEveryPath && id > maxId) {\n          maxId = id;\n          maxState = state;\n        }\n      }\n    }\n    return maxState ?? this._createRootPath();\n  }\n\n  /**\n   * We might be merging paths where some of them had fork points after the initial forking.\n   * We need all the paths to point to the least common fork point and contain all the changes\n   * that happened after it.\n   */\n  private _moveUpToForkPoint(forkPoint: PathState<A>, path: PathState<A>): PathState<A> {\n    const isForkPointInPath = path.chosenPath[forkPoint.head.id] == null || path.forkPoint == null;\n    if (isForkPointInPath) {\n      return path;\n    }\n    if (forkPoint.head.id === path.forkPoint?.head.id) {\n      return path;\n    }\n    let it = path.forkPoint!;\n    while (it.head.id !== forkPoint.head.id) {\n      it.forkIssuers.forEach((iss) => path.forkIssuers.add(iss));\n      it.forkChangedSubjects.forEach((m) => path.forkChangedSubjects.add(m));\n      it = it!.forkPoint!;\n      path.forkPoint = it;\n    }\n    return path;\n  }\n\n  private _mergePaths(convergedPaths: PathState<A>[]): PathMergeResult<A> {\n    invariant(convergedPaths.length >= 1);\n    if (convergedPaths.length === 1) {\n      return { type: 'merged', path: convergedPaths[0] };\n    }\n    const forkPoint = this._leastCommonAncestor(convergedPaths);\n    log('merging paths', () => ({\n      forkPointId: forkPoint.head.id,\n      pathCount: convergedPaths.length,\n      forkPoints: convergedPaths.map((fp) => fp.forkPoint?.head.id),\n    }));\n    const paths = convergedPaths.map((p) => this._moveUpToForkPoint(forkPoint, p));\n    invariant(forkPoint);\n    const result: PathState<A> = {\n      forkPoint: forkPoint.forkPoint,\n      chosenPath: { ...forkPoint.chosenPath, [forkPoint.head.id]: [] },\n      stateOverrides: forkPoint.stateOverrides,\n      credentials: new ComplexSet(PublicKey.hash, forkPoint.credentials),\n      forkIssuers: new ComplexSet(PublicKey.hash, forkPoint.forkIssuers),\n      forkChangedSubjects: new ComplexSet(PublicKey.hash, forkPoint.forkChangedSubjects),\n      state: forkPoint.state.mapValues((v) => v),\n      head: paths[0].head,\n    };\n    const subjectToBranch = new ComplexMap<PublicKey, PathState<A>>(PublicKey.hash);\n    for (const path of paths) {\n      log('processing a path', () => ({\n        choices: toChosenPath(path),\n        modified: path.forkChangedSubjects,\n        forkIssuers: path.forkIssuers,\n        state: path.state.mapValues((v) => this._stateHandler.toLogString(v.assertion)),\n      }));\n      path.forkIssuers.forEach((iss) => result.forkIssuers.add(iss));\n      path.credentials.forEach((cred) => result.credentials.add(cred));\n      result.chosenPath![forkPoint.head.id].push(...(path.chosenPath![forkPoint.head.id] ?? []));\n      for (const modifiedSubject of path.forkChangedSubjects) {\n        const existingBranch = subjectToBranch.get(modifiedSubject);\n        if (existingBranch == null || this._shouldOverrideCredential(existingBranch, path, modifiedSubject)) {\n          subjectToBranch.set(modifiedSubject, path);\n        }\n      }\n    }\n    const replayPaths = new Set<PathState<A>>();\n    const addReplayPath = replayPaths.add.bind(replayPaths);\n    for (const [subject, branch] of subjectToBranch.entries()) {\n      result.forkChangedSubjects.add(subject);\n      const vertex = branch.state.get(subject)!;\n      result.state.set(subject, vertex);\n      log('set subject state', () => ({ subject, state: this._stateHandler.toLogString(vertex.assertion) }));\n      const otherPaths = paths.filter((p) => p !== branch);\n      this._stateHandler.getConflictingPaths(otherPaths, vertex).forEach(addReplayPath);\n    }\n    if (replayPaths.size > 0) {\n      return {\n        type: 'replay_required',\n        replay: [...replayPaths.values()],\n        from: forkPoint,\n        stateOverrides: subjectToBranch.mapValues((v, key) => v.state.get(key)!),\n      };\n    }\n    return { type: 'merged', path: result };\n  }\n\n  /**\n   * A candidate credential is preferred over the existing credential if:\n   *  1. It is the merge-point, because it's the last credential that was issued in awareness of all\n   *  the previously existing ones.\n   *  2. A path where candidate was set contains existing credential in it, which means that the candidate\n   *  was issued after the existing credential by a legitimate issuer.\n   *  3. A state-specific logic (_stateHandler) is able to justify using the candidate credential.\n   *  4. The path where candidate was set has more issuers than the existing path (longer branch).\n   *  5. The issuance time of the candidate is after the issuance time of the existing credential (LWW).\n   */\n  private _shouldOverrideCredential(\n    existing: PathState<A>,\n    candidate: PathState<A>,\n    modifiedSubject: PublicKey,\n  ): boolean {\n    const candidateVertex = candidate.state.get(modifiedSubject)!;\n    const currentVertex = existing.state.get(modifiedSubject)!;\n    if (candidateVertex.id === currentVertex.id) {\n      return false;\n    }\n    // During merge all paths are pointing to the same head, which is the merge point.\n    const mergePointId = existing.head.id;\n    if (candidateVertex.id === mergePointId || currentVertex.id === mergePointId) {\n      log('merge point chosen to break the tie', { mergePointId: existing.head.id });\n      return mergePointId === candidateVertex.id;\n    }\n    const candidateCredential = candidateVertex.credential!;\n    const currentCredential = currentVertex.credential!;\n    // A credential is contained in a branch where another credential for this subject was issued.\n    if (existing.credentials.has(candidateCredential.id!) !== candidate.credentials.has(currentCredential.id!)) {\n      log('one of the credentials was overridden in another branch', {\n        current: currentVertex.id,\n        candidate: candidateVertex.id,\n      });\n      return candidate.credentials.has(currentCredential.id!);\n    }\n    // Give a chance to state-specific conflict resolution logic.\n    const winningCredential = this._stateHandler.tryPickWinningUpdate(\n      existing,\n      currentCredential,\n      candidate,\n      candidateCredential,\n    );\n    if (winningCredential != null) {\n      return winningCredential === candidateCredential;\n    }\n    if (candidate.forkIssuers.size !== existing.forkIssuers.size) {\n      log('longer issuers branch used to break the tie', {\n        issuerCount: [existing.forkIssuers.size, candidate.forkIssuers.size],\n      });\n      return candidate.forkIssuers.size > existing.forkIssuers.size;\n    }\n    log('issuance date used to break the tie');\n    return candidateCredential.issuanceDate.getTime() > currentCredential.issuanceDate.getTime();\n  }\n\n  private _createRootPath(): PathState<A> {\n    return {\n      head: this._root,\n      chosenPath: {},\n      forkIssuers: new ComplexSet(PublicKey.hash),\n      forkChangedSubjects: new ComplexSet(PublicKey.hash),\n      state: new ComplexMap<PublicKey, ChainVertex<A>>(PublicKey.hash),\n      credentials: new ComplexSet(PublicKey.hash),\n    };\n  }\n}\n\nexport interface StateScope<A> {\n  head?: { id: number };\n  state: ReadonlyMap<PublicKey, ChainVertex<A>>;\n  stateOverrides?: ReadonlyMap<PublicKey, ChainVertex<A>>;\n}\n\nexport interface CredentialGraphStateHandler<Assertion, State> {\n  hasStateChanged(s1?: State, s2?: State): boolean;\n\n  createState(credential: Credential, assertion: Assertion): State;\n\n  isUpdateAllowed: (scope: StateScope<Assertion>, update: Credential, assertion: Assertion) => boolean;\n\n  getConflictingPaths(paths: PathState<Assertion>[], update: ChainVertex<Assertion>): PathState<Assertion>[];\n\n  tryPickWinningUpdate(\n    scope1: StateScope<Assertion>,\n    update1: Credential,\n    scope2: StateScope<Assertion>,\n    update2: Credential,\n  ): Credential | null;\n\n  toLogString(assertion: Assertion): string;\n}\n\nexport interface PathState<A> {\n  /**\n   * The current vertex position in path, always advances.\n   */\n  head: ChainVertex<A>;\n  /**\n   * Subject info local to the current path.\n   */\n  state: ComplexMap<PublicKey, ChainVertex<A>>;\n  /**\n   * Used during path replay to throw away cascading concurrent modifications.\n   * Overrides pathState.\n   */\n  stateOverrides?: ComplexMap<PublicKey, ChainVertex<A>>;\n  /**\n   * Used to faster search of conflicting branches. Is different from pathState.keys()\n   * because pathState is not reset on forks.\n   */\n  forkChangedSubjects: ComplexSet<PublicKey>;\n  /**\n   * Used to find winning branches. A branch wins if it had more participants.\n   * Ties are broken using credential issuance date.\n   */\n  forkIssuers: ComplexSet<PublicKey>;\n  /**\n   * All the credentials processed during this path traversal.\n   */\n  credentials: ComplexSet<PublicKey>;\n  /**\n   * PathState where we had multiple children in the current vertex.\n   * Will be merged with child branches when they converge.\n   */\n  forkPoint?: PathState<A>;\n  /**\n   * Used for a particular path replay with stateOverrides for conflict resolution\n   * forkVertexId is mapped to child vertex selection.\n   * Contains choices that lead to the current state. Value is an array when\n   * some branches converged before converging with the remaining branches.\n   */\n  chosenPath: { [forkVertexId: number]: ChainVertex<A>[] };\n}\n\nexport interface ChainVertex<Assertion> {\n  /**\n   * The field is missing on root and sentinel vertices. Assertion is not undefined to avoid\n   * always asserting two fields.\n   */\n  credential?: Credential;\n  assertion: Assertion;\n  /**\n   * Local incrementing counter used to form paths. Is used only for causality resolution.\n   */\n  id: number;\n  /**\n   * Parents references are used to handle divergent branch merge-points.\n   */\n  parents: ChainVertex<Assertion>[];\n  /**\n   * Child references are traversed when computing the current state.\n   */\n  children: ChainVertex<Assertion>[];\n}\n\ntype PathMergeResult<A> = SuccessfulMergeResult<A> | ReplayRequiredMergeResult<A>;\n\ninterface SuccessfulMergeResult<A> {\n  type: 'merged';\n  path: PathState<A>;\n}\n\ninterface ReplayRequiredMergeResult<A> {\n  type: 'replay_required';\n  from: PathState<A>;\n  replay: PathState<A>[];\n  stateOverrides: ComplexMap<PublicKey, ChainVertex<A>>;\n}\n\nconst toChosenPath = <A>(path: PathState<A>) => {\n  return Object.fromEntries(Object.entries(path.chosenPath!).map(([k, vs]) => [k, vs.map((v) => v.id)]));\n};\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Credential, type ProfileDocument, SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { ComplexMap } from '@dxos/util';\n\nimport { getCredentialAssertion } from '../credentials';\nimport {\n  type ChainVertex,\n  CredentialGraph,\n  type CredentialGraphStateHandler,\n  type PathState,\n  type StateScope,\n} from '../graph/credential-graph';\n\nexport interface MemberInfo {\n  key: PublicKey;\n  role: SpaceMember.Role;\n  credential: Credential;\n  assertion: SpaceMember;\n  profile?: ProfileDocument;\n}\n\n/**\n * Tracks the list of members (with roles) for the space.\n * Provides a list of admitted feeds.\n */\nexport class MemberStateMachine implements CredentialGraphStateHandler<SpaceMember, MemberInfo> {\n  private _ownerKey: PublicKey | undefined;\n  private _memberProfiles = new ComplexMap<PublicKey, ProfileDocument | undefined>(PublicKey.hash);\n  private _hashgraph = new CredentialGraph<SpaceMember, MemberInfo>(this);\n\n  readonly onMemberRoleChanged = this._hashgraph.onSubjectStateChanged;\n\n  constructor(private readonly _spaceKey: PublicKey) {}\n\n  get creator(): MemberInfo | undefined {\n    return this._ownerKey && this._hashgraph.getSubjectState(this._ownerKey);\n  }\n\n  get members(): ReadonlyMap<PublicKey, MemberInfo> {\n    return this._hashgraph.getState();\n  }\n\n  get membershipChainHeads(): PublicKey[] {\n    return this._hashgraph.getLeafIds();\n  }\n\n  getRole(member: PublicKey): SpaceMember.Role {\n    return this._getRole(this._hashgraph.getGlobalStateScope(), member);\n  }\n\n  /**\n   * Processes the SpaceMember credential.\n   * Assumes the credential is already pre-verified and the issuer has been authorized to issue credentials of this type.\n   */\n  async process(credential: Credential): Promise<void> {\n    const assertion = getCredentialAssertion(credential);\n\n    switch (assertion['@type']) {\n      case 'dxos.halo.credentials.SpaceMember': {\n        invariant(assertion.spaceKey.equals(this._spaceKey));\n        if (this._ownerKey == null && credential.issuer === this._spaceKey) {\n          this._ownerKey = credential.subject.id;\n        }\n        if (assertion.profile != null) {\n          this._memberProfiles.set(credential.subject.id, assertion.profile);\n        }\n        await this._hashgraph.addVertex(credential, assertion);\n        break;\n      }\n      case 'dxos.halo.credentials.MemberProfile': {\n        const member = this._hashgraph.getSubjectState(credential.subject.id);\n        if (member) {\n          member.profile = assertion.profile;\n        } else {\n          log.warn('Member not found', { id: credential.subject.id });\n        }\n        this._memberProfiles.set(credential.subject.id, assertion.profile);\n        break;\n      }\n      default:\n        throw new Error('Invalid assertion type');\n    }\n  }\n\n  public createState(credential: Credential, assertion: SpaceMember): MemberInfo {\n    const memberKey = credential.subject.id;\n    return {\n      key: memberKey,\n      role: assertion.role,\n      credential,\n      assertion,\n      profile: this._memberProfiles.get(memberKey),\n    };\n  }\n\n  public isUpdateAllowed(scope: StateScope<SpaceMember>, credential: Credential, assertion: SpaceMember): boolean {\n    if (assertion.role === SpaceMember.Role.OWNER) {\n      return credential!.issuer.equals(this._spaceKey);\n    }\n    const issuer = credential.issuer;\n    const isChangingOwnRole = issuer.equals(credential.subject.id);\n    if (isChangingOwnRole) {\n      return false;\n    }\n    if (issuer.equals(assertion.spaceKey)) {\n      return true;\n    }\n    const issuerRole = this._getRole(scope, issuer);\n    return issuerRole === SpaceMember.Role.ADMIN || issuerRole === SpaceMember.Role.OWNER;\n  }\n\n  public getConflictingPaths(\n    paths: PathState<SpaceMember>[],\n    update: ChainVertex<SpaceMember>,\n  ): PathState<SpaceMember>[] {\n    // a member can't be an issuer in a concurrent branch if we decided to remove or revoke admin permissions during merge\n    if (update.assertion.role !== SpaceMember.Role.REMOVED && update.assertion.role !== SpaceMember.Role.EDITOR) {\n      return [];\n    }\n    const memberId = update.credential!.subject.id!;\n    return paths.filter((p) => p.forkIssuers.has(memberId));\n  }\n\n  public tryPickWinningUpdate(\n    scope1: StateScope<SpaceMember>,\n    update1: Credential,\n    scope2: StateScope<SpaceMember>,\n    update2: Credential,\n  ): Credential | null {\n    const path1IssuerRole = this._getRole(scope1, update1.issuer);\n    const path2IssuerRole = this._getRole(scope2, update2.issuer);\n    if ((path2IssuerRole === SpaceMember.Role.OWNER) !== (path1IssuerRole === SpaceMember.Role.OWNER)) {\n      log('owner decision used to break the tie');\n      return path1IssuerRole === SpaceMember.Role.OWNER ? update1 : update2;\n    }\n    return null;\n  }\n\n  public toLogString(assertion: SpaceMember | undefined): string {\n    const role = assertion?.role ?? SpaceMember.Role.REMOVED;\n    return Object.entries(SpaceMember.Role).find(([_, value]) => value === role)![0];\n  }\n\n  public hasStateChanged(s1?: MemberInfo, s2?: MemberInfo): boolean {\n    return s1?.role !== s2?.role;\n  }\n\n  private _getRole(scope: StateScope<SpaceMember>, memberId: PublicKey): SpaceMember.Role {\n    if (this._ownerKey?.equals(memberId)) {\n      return SpaceMember.Role.OWNER;\n    }\n    const realRole = scope.state.get(memberId)?.assertion?.role ?? SpaceMember.Role.REMOVED;\n    if (scope.stateOverrides != null) {\n      const override = scope.stateOverrides.get(memberId);\n      if (override != null) {\n        log('member role overridden in path', () => ({\n          headId: scope.head?.id,\n          roleOverride: this.toLogString(override.assertion),\n          realRole: this.toLogString(scope.state.get(memberId)?.assertion),\n        }));\n        return override.assertion.role;\n      }\n    }\n    return realRole;\n  }\n}\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { runInContextAsync, synchronized } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type TypedMessage } from '@dxos/protocols/proto';\nimport { type Credential, MembershipPolicy, SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';\nimport { type AsyncCallback, Callback, ComplexMap, ComplexSet } from '@dxos/util';\n\nimport { getCredentialAssertion, verifyCredential } from '../credentials';\nimport { type CredentialProcessor } from '../processor/credential-processor';\nimport { type FeedInfo, FeedStateMachine } from './feed-state-machine';\nimport { InvitationStateMachine } from './invitation-state-machine';\nimport { type MemberInfo, MemberStateMachine } from './member-state-machine';\n\nexport interface SpaceState {\n  readonly members: ReadonlyMap<PublicKey, MemberInfo>;\n  readonly membershipChainHeads: PublicKey[];\n  readonly feeds: ReadonlyMap<PublicKey, FeedInfo>;\n  readonly credentials: Credential[];\n  readonly genesisCredential: Credential | undefined;\n  readonly tags: string[];\n  readonly membershipPolicy: MembershipPolicy;\n  readonly creator: MemberInfo | undefined;\n  readonly invitations: ReadonlyMap<PublicKey, DelegateSpaceInvitation>;\n\n  addCredentialProcessor(processor: CredentialProcessor): Promise<void>;\n  removeCredentialProcessor(processor: CredentialProcessor): Promise<void>;\n\n  getCredentialsOfType(type: TypedMessage['@type']): Credential[];\n\n  getMemberRole(memberKey: PublicKey): SpaceMember.Role;\n  hasMembershipManagementPermission(memberKey: PublicKey): boolean;\n}\n\nexport type ProcessOptions = {\n  sourceFeed: PublicKey;\n  skipVerification?: boolean;\n};\n\nexport type CredentialEntry = {\n  credential: Credential;\n  sourceFeed: PublicKey;\n  revoked: boolean;\n};\n\n/**\n * Validates and processes credentials for a single space.\n * Keeps a list of members and feeds.\n * Keeps and in-memory index of credentials and allows to query them.\n */\nexport class SpaceStateMachine implements SpaceState {\n  private readonly _members: MemberStateMachine;\n  private readonly _feeds: FeedStateMachine;\n  private readonly _invitations = new InvitationStateMachine();\n  private readonly _credentials: CredentialEntry[] = [];\n  private readonly _credentialsById = new ComplexMap<PublicKey, CredentialEntry>(PublicKey.hash);\n  private readonly _processedCredentials = new ComplexSet<PublicKey>(PublicKey.hash);\n\n  private _genesisCredential: Credential | undefined;\n  private _tags: string[] = [];\n  private _membershipPolicy: MembershipPolicy = MembershipPolicy.INVITE;\n  private _credentialProcessors: CredentialConsumer<any>[] = [];\n\n  readonly onCredentialProcessed = new Callback<AsyncCallback<Credential>>();\n  readonly onMemberRoleChanged: Callback<AsyncCallback<MemberInfo[]>>;\n  readonly onFeedAdmitted: Callback<AsyncCallback<FeedInfo>>;\n  readonly onDelegatedInvitation = this._invitations.onDelegatedInvitation;\n  readonly onDelegatedInvitationRemoved = this._invitations.onDelegatedInvitationRemoved;\n\n  constructor(private readonly _spaceKey: PublicKey) {\n    this._members = new MemberStateMachine(this._spaceKey);\n    this._feeds = new FeedStateMachine(this._spaceKey);\n    this.onMemberRoleChanged = this._members.onMemberRoleChanged;\n    this.onFeedAdmitted = this._feeds.onFeedAdmitted;\n  }\n\n  get creator(): MemberInfo | undefined {\n    return this._members.creator;\n  }\n\n  get members(): ReadonlyMap<PublicKey, MemberInfo> {\n    return this._members.members;\n  }\n\n  get membershipChainHeads(): PublicKey[] {\n    return this._members.membershipChainHeads;\n  }\n\n  get feeds(): ReadonlyMap<PublicKey, FeedInfo> {\n    return this._feeds.feeds;\n  }\n\n  get credentials(): Credential[] {\n    return this._credentials.map((entry) => entry.credential);\n  }\n\n  get credentialEntries(): CredentialEntry[] {\n    return this._credentials;\n  }\n\n  get genesisCredential(): Credential | undefined {\n    return this._genesisCredential;\n  }\n\n  get tags(): string[] {\n    return this._tags;\n  }\n\n  get membershipPolicy(): MembershipPolicy {\n    return this._membershipPolicy;\n  }\n\n  get invitations(): ReadonlyMap<PublicKey, DelegateSpaceInvitation> {\n    return this._invitations.invitations;\n  }\n\n  async addCredentialProcessor(processor: CredentialProcessor): Promise<void> {\n    if (this._credentialProcessors.find((p) => p.processor === processor)) {\n      throw new Error('Credential processor already added.');\n    }\n\n    const consumer = new CredentialConsumer(\n      processor,\n      async () => {\n        for (const credential of this.credentials) {\n          await consumer._process(credential);\n        }\n\n        // NOTE: It is important to set this flag after immediately after processing existing credentials.\n        // Otherwise, we might miss some credentials.\n        // Having an `await` statement between the end of the loop and setting the flag would cause a race condition.\n        consumer._isReadyForLiveCredentials = true;\n      },\n      async () => {\n        this._credentialProcessors = this._credentialProcessors.filter((p) => p !== consumer);\n      },\n    );\n    this._credentialProcessors.push(consumer);\n\n    await consumer.open();\n  }\n\n  async removeCredentialProcessor(processor: CredentialProcessor): Promise<void> {\n    const consumer = this._credentialProcessors.find((p) => p.processor === processor);\n    await consumer?.close();\n  }\n\n  getCredentialsOfType(type: TypedMessage['@type']): Credential[] {\n    return this.credentials.filter((credential) => getCredentialAssertion(credential)['@type'] === type);\n  }\n\n  /**\n   * @param credential Message to process.\n   * @param fromFeed Key of the feed where this credential is recorded.\n   */\n  @synchronized\n  async process(credential: Credential, { sourceFeed, skipVerification }: ProcessOptions): Promise<boolean> {\n    if (credential.id) {\n      if (this._processedCredentials.has(credential.id)) {\n        return true;\n      }\n      this._processedCredentials.add(credential.id);\n    }\n\n    if (!skipVerification) {\n      const result = await verifyCredential(credential);\n      if (result.kind !== 'pass') {\n        log.warn(`Invalid credential: ${result.errors.join(', ')}`);\n        return false;\n      }\n    }\n\n    const assertion = getCredentialAssertion(credential);\n    switch (assertion['@type']) {\n      case 'dxos.halo.credentials.SpaceGenesis': {\n        if (this._genesisCredential) {\n          log.warn('Space already has a genesis credential.');\n          return false;\n        }\n        if (!credential.issuer.equals(this._spaceKey)) {\n          log.warn('Space genesis credential must be issued by space.');\n          return false;\n        }\n        if (!credential.subject.id.equals(this._spaceKey)) {\n          log.warn('Space genesis credential must be issued to space.');\n          return false;\n        }\n        this._genesisCredential = credential;\n        this._tags = assertion.tags ?? [];\n        this._membershipPolicy = assertion.membershipPolicy ?? MembershipPolicy.INVITE;\n        break;\n      }\n\n      case 'dxos.halo.credentials.SpaceMember': {\n        if (!assertion.spaceKey.equals(this._spaceKey)) {\n          break; // Ignore credentials for other spaces.\n        }\n\n        if (!this._genesisCredential) {\n          log.warn('Space must have a genesis credential before adding members.');\n          return false;\n        }\n        if (!this._canInviteNewMembers(credential.issuer)) {\n          log.warn(`Space member is not authorized to invite new members: ${credential.issuer}`);\n          return false;\n        }\n\n        await this._members.process(credential);\n        await this._invitations.process(credential);\n        break;\n      }\n\n      case 'dxos.halo.credentials.MemberProfile': {\n        if (!this._genesisCredential) {\n          log.warn('Space must have a genesis credential before adding members.');\n          return false;\n        }\n\n        await this._members.process(credential);\n        break;\n      }\n\n      case 'dxos.halo.credentials.AdmittedFeed': {\n        if (!this._genesisCredential) {\n          log.warn('Space must have a genesis credential before admitting feeds.');\n          return false;\n        }\n\n        // We don't do any validation on feed admission since we would perform the same validation on the credentials inside .\n        await this._feeds.process(credential, sourceFeed);\n        break;\n      }\n      case 'dxos.halo.invitations.CancelDelegatedInvitation':\n      case 'dxos.halo.invitations.DelegateSpaceInvitation': {\n        if (!this._canInviteNewMembers(credential.issuer)) {\n          log.warn(`Invalid invitation, space member is not authorized to invite new members: ${credential.issuer}`);\n          return false;\n        }\n        await this._invitations.process(credential);\n        break;\n      }\n    }\n\n    const newEntry: CredentialEntry = { credential, sourceFeed, revoked: false };\n    this._credentials.push(newEntry);\n\n    // TODO(dmaretskyi): Invariant on every credential having an id?\n    if (credential.id) {\n      this._credentialsById.set(credential.id, newEntry);\n    }\n\n    for (const processor of this._credentialProcessors) {\n      if (processor._isReadyForLiveCredentials) {\n        await processor._process(credential);\n      }\n    }\n\n    await this.onCredentialProcessed.callIfSet(credential);\n    return true;\n  }\n\n  public getMemberRole(memberKey: PublicKey): SpaceMember.Role {\n    return this._members.getRole(memberKey);\n  }\n\n  public hasMembershipManagementPermission(memberKey: PublicKey): boolean {\n    return this._canInviteNewMembers(memberKey);\n  }\n\n  private _canInviteNewMembers(key: PublicKey): boolean {\n    if (this._membershipPolicy === MembershipPolicy.LOCKED) {\n      // When locked, only the space key can add the initial owner during genesis.\n      // Once a member exists, no new members can be added.\n      return key.equals(this._spaceKey) && this._members.members.size === 0;\n    }\n    return (\n      key.equals(this._spaceKey) ||\n      this._members.getRole(key) === SpaceMember.Role.ADMIN ||\n      this._members.getRole(key) === SpaceMember.Role.OWNER\n    );\n  }\n}\n\n// TODO(dmaretskyi): Simplify.\nclass CredentialConsumer<T extends CredentialProcessor> {\n  private _ctx = new Context();\n\n  /**\n   * @internal\n   * Processor is ready to process live credentials.\n   * NOTE: Setting this flag before all existing credentials are processed will cause them to be processed out of order.\n   * Set externally.\n   */\n  _isReadyForLiveCredentials = false;\n\n  constructor(\n    public readonly processor: T,\n    private readonly _onOpen: () => Promise<void>,\n    private readonly _onClose: () => Promise<void>,\n  ) {}\n\n  /**\n   * @internal\n   */\n  async _process(credential: Credential): Promise<void> {\n    await runInContextAsync(this._ctx, async () => {\n      await this.processor.processCredential(credential);\n    });\n  }\n\n  async open(): Promise<void> {\n    if (this._ctx.disposed) {\n      throw new Error('CredentialProcessor is disposed');\n    }\n\n    await this._onOpen();\n  }\n\n  async close(): Promise<void> {\n    await this._ctx.dispose();\n\n    await this._onClose();\n  }\n}\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { Trigger } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Chain, type Credential, type DeviceProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';\nimport { ComplexMap } from '@dxos/util';\n\nimport { getCredentialAssertion, isValidAuthorizedDeviceCredential } from '../credentials';\nimport { type CredentialProcessor } from './credential-processor';\n\nexport type DeviceStateMachineProps = {\n  identityKey: PublicKey;\n  deviceKey: PublicKey;\n  onUpdate?: () => void;\n};\n\n/**\n * Processes device invitation credentials.\n */\nexport class DeviceStateMachine implements CredentialProcessor {\n  // TODO(burdon): Return values via getter.\n  public readonly authorizedDeviceKeys = new ComplexMap<PublicKey, DeviceProfileDocument>(PublicKey.hash);\n\n  public readonly deviceChainReady = new Trigger();\n\n  public deviceCredentialChain?: Chain;\n\n  constructor(private readonly _params: DeviceStateMachineProps) {}\n\n  async processCredential(credential: Credential): Promise<void> {\n    log('processing credential...', {\n      identityKey: this._params.identityKey,\n      deviceKey: this._params.deviceKey,\n      credential,\n    });\n\n    // Save device keychain credential when processed by the space state machine.\n    if (isValidAuthorizedDeviceCredential(credential, this._params.identityKey, this._params.deviceKey)) {\n      this.deviceCredentialChain = { credential };\n      this.deviceChainReady.wake();\n    }\n\n    const assertion = getCredentialAssertion(credential);\n\n    switch (assertion['@type']) {\n      case 'dxos.halo.credentials.AuthorizedDevice': {\n        // We don't need to validate that the device is already added since the credentials are considered idempotent.\n        // In the future, when we will have device-specific attributes, we should join them from all concurrent credentials.\n        this.authorizedDeviceKeys.set(assertion.deviceKey, this.authorizedDeviceKeys.get(assertion.deviceKey) ?? {});\n\n        log('added device', {\n          localDeviceKey: this._params.deviceKey,\n          deviceKey: assertion.deviceKey,\n          size: this.authorizedDeviceKeys.size,\n        });\n        this._params.onUpdate?.();\n        break;\n      }\n\n      case 'dxos.halo.credentials.DeviceProfile': {\n        invariant(this.authorizedDeviceKeys.has(credential.subject.id), 'Device not found.');\n\n        if (assertion && credential.subject.id.equals(this._params.deviceKey)) {\n          log.trace('dxos.halo.device', {\n            deviceKey: credential.subject.id,\n            profile: assertion.profile,\n          });\n        }\n\n        this.authorizedDeviceKeys.set(credential.subject.id, assertion.profile);\n        this._params.onUpdate?.();\n        break;\n      }\n    }\n  }\n}\n","//\n// Copyright 2022 DXOS.org\n//\n\nimport { type PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { type Credential, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';\n\nimport { getCredentialAssertion } from '../credentials';\nimport { type CredentialProcessor } from './credential-processor';\n\nexport type ProfileStateMachineProps = {\n  identityKey: PublicKey;\n  onUpdate?: () => void;\n};\n\n/**\n * Processes device invitation credentials.\n */\nexport class ProfileStateMachine implements CredentialProcessor {\n  // TODO(burdon): Return values via getter.\n  public profile?: ProfileDocument;\n\n  constructor(private readonly _params: ProfileStateMachineProps) {}\n\n  async processCredential(credential: Credential): Promise<void> {\n    const assertion = getCredentialAssertion(credential);\n    switch (assertion['@type']) {\n      case 'dxos.halo.credentials.IdentityProfile': {\n        if (\n          !credential.issuer.equals(this._params.identityKey) ||\n          !credential.subject.id.equals(this._params.identityKey)\n        ) {\n          log.warn('Invalid profile credential', { expectedIdentity: this._params.identityKey, credential });\n          return;\n        }\n\n        // TODO(dmaretskyi): Extra validation for the credential?\n        this.profile = assertion.profile;\n        log('updated profile', {\n          identityKey: this._params.identityKey,\n          profile: this.profile,\n        });\n        this._params.onUpdate?.();\n        break;\n      }\n    }\n  }\n}\n"],"mappings":"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"}