@dxos/credentials 0.8.4-main.ae835ea → 0.8.4-main.bc674ce

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "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/credential-factory.ts", "../../../src/credentials/verifier.ts", "../../../src/credentials/credential-generator.ts", "../../../src/presentations/presentation.ts", "../../../src/presentations/verifier.ts", "../../../src/state-machine/space-state-machine.ts", "../../../src/state-machine/feed-state-machine.ts", "../../../src/state-machine/invitation-state-machine.ts", "../../../src/state-machine/member-state-machine.ts", "../../../src/graph/credential-graph.ts", "../../../src/processor/device-state-machine.ts", "../../../src/processor/profile-state-machine.ts"],
4
- "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 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 TYPES, type TypedMessage } 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 { 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 CreateCredentialSignerParams = {\n subject: PublicKey;\n assertion: TypedMessage;\n nonce?: Uint8Array;\n parentCredentialIds?: PublicKey[];\n};\n\nexport type CreateCredentialParams = {\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}: CreateCredentialParams): 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: CreateCredentialSignerParams) => 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 { 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 } 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 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 ): 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 },\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): 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 },\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';\n\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';\n\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 { 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, 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';\n\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 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 _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 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 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 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 { 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 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 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 { 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';\n\nimport { type CredentialProcessor } from './credential-processor';\n\nexport type DeviceStateMachineParams = {\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: DeviceStateMachineParams) {}\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';\n\nimport { type CredentialProcessor } from './credential-processor';\n\nexport type ProfileStateMachineParams = {\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: ProfileStateMachineParams) {}\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"],
5
- "mappings": "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",
4
+ "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 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 TYPES, type TypedMessage } 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 { 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 { 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 } 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 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 ): 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 },\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): 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 },\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';\n\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';\n\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 { 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, 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';\n\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 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 _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 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 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 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 { 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 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 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 { 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';\n\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';\n\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"],
5
+ "mappings": ";;;AAIA,SAASA,oBAAoB;AAC7B,SAASC,aAAaC,iBAAiB;AACvC,SAASC,kBAAkB;AAE3B,IAAMC,sBAAsB,IAAIC,WAAmCC,UAAUC,IAAI;AAM1E,IAAMC,2BAA2B,OAAOC,gBAAAA;AAC7C,QAAMC,cAAcN,oBAAoBO,IAAIF,WAAAA;AAC5C,MAAIC,gBAAgBE,QAAW;AAC7B,WAAOF;EACT;AAEA,QAAMG,SAAS,MAAMC,aAAaD,OAAO,WAAWJ,YAAYM,aAAY,CAAA;AAE5E,QAAMC,QAAQ,IAAIC,WAAWJ,MAAAA,EAAQK,MAAM,GAAGC,YAAYC,UAAU;AACpE,QAAMC,cAAcF,YAAYG,OAAON,KAAAA;AACvCZ,sBAAoBmB,IAAId,aAAaY,WAAAA;AACrC,SAAOA;AACT;;;ACHO,IAAMG,wBAAwC,YAAYC,OAAOC,KAAK,MAAA;AAEtE,IAAMC,yBAA0C,OAAOC,YAAYC,WAAW;;;ACrBrF,SAASC,kBAAkBC,0BAA0B;AAErD,SAASC,qBAAqB;AAC9B,SAASC,iBAAiB;;AAMnB,IAAMC,qBAAqB,MAAcJ,iBAAAA;AAKzC,IAAMK,wBAAwB,CAACC,eAAAA;AACpCH,YAAUG,YAAAA,QAAAA;;;;;;;;;AACV,QAAMC,OAAON,mBAAmBK,UAAAA;AAChC,SAAOJ,cAAcK,IAAAA;AACvB;;;ACbO,IAAMC,mBAAmB,CAACC,SAAS,MAAC;AACzC,MAAIC,WAAW;AACf,WAASC,IAAI,GAAGA,IAAIF,QAAQE,KAAK;AAC/BD,gBAAY,GAAGE,KAAKC,MAAMD,KAAKE,OAAM,IAAK,EAAA,CAAA;EAC5C;AAEA,SAAOJ;AACT;;;ACZA,OAAOK,qBAAqB;AAE5B,SAASC,aAAAA,kBAAiB;AAE1B,SAASC,iBAAiB;AAC1B,SAASC,qBAAqB;AAMvB,IAAMC,4BAA4B,CAACC,eAAAA;AACxC,QAAMC,OAAO;IACX,GAAGD;IACHE,OAAO;MACL,GAAGF,WAAWE;MACdC,OAAO,IAAIC,WAAAA;MACXC,OAAOC;IACT;EACF;AACA,MAAIL,KAAKM,qBAAqBC,WAAW,GAAG;AAC1C,WAAOP,KAAKM;EACd;AACA,SAAON,KAAKQ;AAEZ,SAAOC,OAAOC,KAAKC,mBAAmBX,IAAAA,CAAAA;AACxC;AAKO,IAAMW,qBAAqB,CAACC,QACjCC,gBAAgBD,KAAK;;;;;;;;EAQnBE,UAAU,SAAqBC,KAAUb,OAAU;AACjD,QAAIa,IAAIC,SAAQ,EAAGC,WAAW,IAAA,KAASF,IAAIC,SAAQ,MAAO,SAAS;AACjE,aAAOX;IACT;AAEA,QAAIH,UAAU,MAAM;AAClB,aAAOG;IACT;AAGA,UAAMa,WAAW,KAAKH,GAAAA;AAEtB,QAAIb,OAAO;AACT,UAAIiB,WAAUC,YAAYlB,KAAAA,GAAQ;AAChC,eAAOA,MAAMmB,MAAK;MACpB;AACA,UAAIZ,OAAOa,SAASpB,KAAAA,GAAQ;AAC1B,eAAOA,MAAMc,SAAS,KAAA;MACxB;AAEA,UAAId,iBAAiBC,YAAY;AAC/B,eAAOoB,cAAcrB,KAAAA,EAAOc,SAAS,KAAA;MACvC;AACA,UAAId,MAAMsB,QAAQtB,MAAMuB,SAAS,UAAU;AACzC,eAAOhB,OAAOC,KAAKR,KAAAA,EAAOc,SAAS,KAAA;MACrC;AACA,UAAIE,oBAAoBQ,WAAW;AAEjC,eAAOR,SAASS,OAAM,EAAGC,OAAO,CAACD,QAAgC,CAACZ,MAAKc,GAAAA,MAAI;AACzEF,iBAAOG,YAAYf,IAAAA,CAAAA,IAAQc;AAC3B,iBAAOF;QACT,GAAG,CAAC,CAAA;MACN;IACF;AAEA,WAAOzB;EACT;AACF,CAAA;AAKF,IAAM4B,cAAc,CAACf,QAAAA;AACnB,QAAMgB,MAAMhB,IAAIM,MAAK;AACrB,SAAO,GAAGU,IAAIC,UAAU,GAAG,CAAA,CAAA,MAAQD,IAAIC,UAAUD,IAAIxB,SAAS,CAAA,CAAA;AAChE;;;ACjFO,IAAM0B,8BAA8B,CAACC,aAA2BC,UAAAA;AACrE,QAAMC,OAAO;IACXF,aAAaA,YAAYG,IAAI,CAACC,eAAeC,+BAA+BD,UAAAA,CAAAA;IAC5EH,OAAO;MACL,GAAGA;MACHK,OAAO,IAAIC,WAAAA;MACXC,OAAOC;IACT;EACF;AAEA,SAAOC,OAAOC,KAAKC,mBAAmBV,IAAAA,CAAAA;AACxC;AAEA,IAAMG,iCAAiC,CAACD,eAAAA;AACtC,QAAMF,OAAO;IACX,GAAGE;IACHH,OAAOG,WAAWH,QACd;MACE,GAAGG,WAAWH;MACdO,OAAOJ,WAAWH,MAAMO,QACpB;QAAEJ,YAAYC,+BAA+BD,WAAWH,MAAMO,MAAMJ,UAAU;MAAE,IAChFK;IACN,IACAA;EACN;AACA,MAAIP,KAAKW,qBAAqBC,WAAW,GAAG;AAC1C,WAAOZ,KAAKW;EACd;AACA,SAAOX;AACT;;;AC7BO,IAAMa,yBAAyB,CAACC,eAAyCA,WAAWC,QAAQC;AAE5F,IAAMC,oCAAoC,CAC/CH,YACAI,aACAC,cAAAA;AAEA,QAAMH,YAAYH,uBAAuBC,UAAAA;AACzC,SACEA,WAAWC,QAAQK,GAAGC,OAAOF,SAAAA,KAC7BL,WAAWQ,OAAOD,OAAOH,WAAAA,KACzBF,UAAU,OAAA,MAAa,4CACvBA,UAAUE,YAAYG,OAAOH,WAAAA,KAC7BF,UAAUG,UAAUE,OAAOF,SAAAA;AAE/B;AAMO,IAAMI,sBAAsB,CACjCT,YACAU,SAC+CV,WAAWC,QAAQC,UAAU,OAAA,MAAaQ;AAEpF,IAAMC,uBACX,CAAwBD,SACxB,CAACV,eACCS,oBAAoBT,YAAYU,IAAAA;;;ACjCpC,SAAsBE,gBAAAA,qBAAoB;AAC1C,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,aAAAA,kBAAiB;;;ACF1B,SAASC,uBAAuB;AAOzB,IAAMC,yBAAyB;AAI/B,IAAMC,mBAAmB,OAAOC,eAAAA;AACrC,MAAIA,WAAWC,qBAAqBC,WAAW,GAAG;AAChD,WAAOF,WAAWC;EACpB;AAEA,MAAI,CAACD,WAAWG,OAAOC,OAAOJ,WAAWK,MAAOC,MAAM,GAAG;AACvD,QAAI,CAACN,WAAWK,MAAOE,OAAO;AAC5B,aAAO;QACLC,MAAM;QACNC,QAAQ;UAAC;;MACX;IACF;AAEA,UAAMC,UAAS,MAAMC,YAAYX,WAAWK,MAAOE,OAAOP,WAAWG,QAAQH,WAAWK,MAAOC,MAAM;AACrG,QAAII,QAAOF,SAAS,QAAQ;AAC1B,aAAOE;IACT;EACF;AAEA,QAAMA,SAAS,MAAME,0BAA0BZ,UAAAA;AAC/C,MAAIU,OAAOF,SAAS,QAAQ;AAC1B,WAAOE;EACT;AAEA,SAAO;IAAEF,MAAM;EAAO;AACxB;AAMO,IAAMI,4BAA4B,OAAOZ,eAAAA;AAC9C,MAAIA,WAAWK,MAAOQ,SAASf,wBAAwB;AACrD,WAAO;MACLU,MAAM;MACNC,QAAQ;QAAC,2BAA2BT,WAAWK,MAAOQ,IAAI;;IAC5D;EACF;AAEA,QAAMC,WAAWC,0BAA0Bf,UAAAA;AAC3C,MAAI,CAAE,MAAMgB,gBAAgBhB,WAAWK,MAAOC,QAAQQ,UAAUd,WAAWK,MAAOY,KAAK,GAAI;AACzF,WAAO;MAAET,MAAM;MAAQC,QAAQ;QAAC;;IAAqB;EACvD;AAEA,SAAO;IAAED,MAAM;EAAO;AACxB;AAKO,IAAMG,cAAc,OACzBJ,OACAW,WACAC,YAAAA;AAEA,QAAMT,SAAS,MAAMX,iBAAiBQ,MAAMP,UAAU;AACtD,MAAIU,OAAOF,SAAS,QAAQ;AAC1B,WAAOE;EACT;AAEA,MAAI,CAACU,kCAAkCb,MAAMP,YAAYkB,WAAWC,OAAAA,GAAU;AAC5E,WAAO;MACLX,MAAM;MACNC,QAAQ;QAAC,wDAAwDU,OAAAA;;IACnE;EACF;AAEA,SAAO;IAAEX,MAAM;EAAO;AACxB;;;;AD9CO,IAAMa,mBAAmB,OAAO,EACrCC,QACAC,QACAC,SACAC,WACAC,YACAC,OACAC,OACAC,oBAAmB,MACG;AACtBC,EAAAA,WAAUL,UAAU,OAAA,GAAU,sBAAA;;;;;;;;;AAC9BK,EAAAA,WAAU,CAAC,CAACJ,eAAe,CAAC,CAACC,OAAO,kFAAA;;;;;;;;;AACpC,MAAIA,OAAO;AACT,UAAMI,SAAS,MAAMC,YAAYL,OAAOJ,QAAQG,UAAAA;AAChDI,IAAAA,WAAUC,OAAOE,SAAS,QAAQ,kBAAA;;;;;;;;;EACpC;AAGA,QAAMC,aAAyB;IAC7BX;IACAY,cAAc,oBAAIC,KAAAA;IAClBZ,SAAS;MACPa,IAAIb;MACJC;IACF;IACAI;IACAS,OAAO;MACLC,MAAMC;MACNC,cAAc,oBAAIL,KAAAA;MAClBd,QAAQI,cAAcH;MACtBmB,OAAO,IAAIC,WAAAA;MACXf;IACF;EACF;AAGA,QAAMgB,gBAAgBC,0BAA0BX,UAAAA;AAChDA,aAAWI,MAAOI,QAAQ,MAAMpB,OAAOwB,KAAKpB,cAAcH,QAAQqB,aAAAA;AAClE,MAAIjB,OAAO;AACTO,eAAWI,MAAOX,QAAQA;EAC5B;AAEAO,aAAWG,KAAKU,WAAUC,KAAK,MAAMC,cAAaC,OAAO,WAAWN,aAAAA,CAAAA;AAEpE,SAAOV;AACT;AAGO,IAAMiB,0BAA0B,CAACjB,eAAAA;AACtC,SAAO;IACL,SAAS;IACTA;EACF;AACF;AAWO,IAAMkB,gCAAgC,CAAC9B,QAAgBC,YAAyC;EACrG8B,WAAW,MAAM9B;EACjBF,kBAAkB,CAAC,EAAEG,SAASC,WAAWG,OAAOC,oBAAmB,MACjER,iBAAiB;IACfC;IACAC;IACAC;IACAC;IACAG;IACAC;EACF,CAAA;AACJ;AAKO,IAAMyB,kCAAkC,CAC7ChC,QACAK,OACAD,gBACsB;EACtB2B,WAAW,MAAM1B,MAAMO,WAAWX;EAClCF,kBAAkB,CAAC,EAAEG,SAASC,WAAWG,OAAOC,oBAAmB,MACjER,iBAAiB;IACfC;IACAC,QAAQI,MAAMO,WAAWX;IACzBG;IACAC;IACAH;IACAC;IACAG;IACAC;EACF,CAAA;AACJ;;;AE9HA,SACE0B,cAIAC,mBACK;AAEP,SAASC,aAAAA,kBAAiB;AAUnB,IAAMC,sBAAN,MAAMA;;;;EACX,YACmBC,SACAC,cACAC,YACjB;SAHiBF,UAAAA;SACAC,eAAAA;SACAC,aAAAA;EAChB;;;;EAKH,MAAMC,mBACJC,UACAC,YACAC,gBACuB;AACvB,WAAO;MACL,MAAMC,iBAAiB;QACrBC,QAAQ,KAAKR;QACbS,QAAQL;QACRM,SAASN;QACTO,WAAW;UACT,SAAS;UACTP;QACF;MACF,CAAA;MAEA,MAAMG,iBAAiB;QACrBC,QAAQ,KAAKR;QACbS,QAAQL;QACRM,SAAS,KAAKT;QACdU,WAAW;UACT,SAAS;UACTP;UACAQ,MAAMC,YAAYC,KAAKC;UACvBC,SAASV;UACTW,gBAAgBZ;QAClB;MACF,CAAA;MAEA,MAAM,KAAKa,oBAAoBd,UAAUC,YAAYc,aAAaC,YAAYC,OAAO;;EAEzF;;;;;;EAOA,MAAMC,uBACJlB,UACAmB,aACAC,WACAnB,YACAoB,SACAR,gBACuB;AACvB,WAAO;MACL,MAAMV,iBAAiB;QACrBC,QAAQ,KAAKR;QACbS,QAAQ,KAAKR;QACbS,SAASa;QACTZ,WAAW;UACT,SAAS;UACTP;UACAQ,MAAMC,YAAYC,KAAKY;UACvBT;QACF;MACF,CAAA;MAEA,MAAM,KAAKC,oBAAoBd,UAAUC,YAAYc,aAAaC,YAAYC,OAAO;MACrF,MAAM,KAAKH,oBAAoBd,UAAUqB,SAASN,aAAaC,YAAYO,IAAI;;EAEnF;;;;;EAMA,MAAMC,0BAA0BJ,WAA2C;AACzE,WAAOjB,iBAAiB;MACtBC,QAAQ,KAAKR;MACbS,QAAQ,KAAKR;MACbS,SAASc;MACTb,WAAW;QACT,SAAS;QACTY,aAAa,KAAKtB;QAClBuB;MACF;IACF,CAAA;EACF;;;;EAKA,MAAMK,oBAAoBb,SAAqD;AAC7E,WAAOT,iBAAiB;MACtBC,QAAQ,KAAKR;MACbS,QAAQ,KAAKR;MACbS,SAAS,KAAKR;MACdS,WAAW;QACT,SAAS;QACTK;MACF;IACF,CAAA;EACF;;;;EAKA,MAAME,oBACJd,UACA0B,SACAC,aACqB;AACrB,WAAOxB,iBAAiB;MACtBC,QAAQ,KAAKR;MACbS,QAAQ,KAAKR;MACbS,SAASoB;MACTnB,WAAW;QACT,SAAS;QACTP;QACAmB,aAAa,KAAKtB;QAClBuB,WAAW,KAAKtB;QAChB6B;MACF;IACF,CAAA;EACF;EAEA,MAAMC,wBAAwBhB,SAA+C;AAC3E,WAAOT,iBAAiB;MACtBC,QAAQ,KAAKR;MACbS,QAAQ,KAAKR;MACbS,SAAS,KAAKT;MACdU,WAAW;QACT,SAAS;QACTK;MACF;IACF,CAAA;EACF;EAEA,MAAMiB,sBAAsB7B,UAA0C;AACpE,WAAOG,iBAAiB;MACtBC,QAAQ,KAAKR;MACbS,QAAQ,KAAKR;MACbS,SAASN;MACTO,WAAW;QACT,SAAS;QACTuB,QAAQ;QACRC,WAAW,IAAIC,WAAAA;MACjB;IACF,CAAA;EACF;AACF;AAGO,IAAMR,4BAA4B,OACvCpB,QACAe,aACAC,cAAAA;AAEA,QAAMa,cAAc,MAAMC,QAAQC,IAAI;IACpC,MAAM/B,OAAOD,iBAAiB;MAC5BG,SAASc;MACTb,WAAW;QACT,SAAS;QACTY;QACAC;MACF;IACF,CAAA;GACD;AAED,SAAOa,YAAYG,IAAI,CAACC,gBAAgB;IACtC,SAAS;IACTA;EACF,EAAA;AACF;AAaO,IAAMC,6BAA6B,OACxClC,QACAe,aACAnB,UACAa,gBACAL,OAAyBC,YAAYC,KAAKC,OAC1C4B,uBAAoC,CAAA,GACpC3B,SACA4B,2BAAAA;AAEA,QAAMP,cAAc,MAAMC,QAAQC,IAAI;IACpC,MAAM/B,OAAOD,iBAAiB;MAC5BG,SAASa;MACTsB,qBAAqBF;MACrBhC,WAAW;QACT,SAAS;QACTP;QACAQ;QACAI;QACAC;QACA2B;MACF;IACF,CAAA;GACD;AAED,SAAOP,YAAYG,IAAI,CAACC,gBAAgB;IACtCA,YAAY;MAAEA;IAAW;EAC3B,EAAA;AACF;AAEO,IAAMK,2CAA2C,OACtDtC,QACAE,SACAqC,eAAAA;AAEA,QAAMN,aAAa,MAAMjC,OAAOD,iBAAiB;IAC/CG;IACAC,WAAW;MACT,SAAS;MACTqC,cAAcD,WAAWC;MACzBC,YAAYF,WAAWE;MACvBC,UAAUH,WAAWG;MACrBtC,MAAMmC,WAAWnC;MACjBuC,UAAUJ,WAAWI;MACrBC,WAAWL,WAAWK;MACtBC,UAAUN,WAAWM;IACvB;EACF,CAAA;AACA,SAAO;IAAEZ,YAAY;MAAEA;IAAW;EAAE;AACtC;AAOO,IAAMa,iDAAiD,OAC5D9C,QACAE,SACAkC,2BAAAA;AAEA,QAAMH,aAAa,MAAMjC,OAAOD,iBAAiB;IAC/CG;IACAC,WAAW;MACT,SAAS;MACT4C,cAAcX;IAChB;EACF,CAAA;AACA,SAAO;IAAEH,YAAY;MAAEA;IAAW;EAAE;AACtC;;;AC9QO,IAAMe,mBAAmB,OAAO,EACrCC,cACAC,QACAC,WACAC,OACAC,MAAK,MAON;AACC,QAAMC,QAAe;IACnBC,MAAMC;IACNC,OAAO,IAAIC,WAAAA;IACXC,cAAc,oBAAIC,KAAAA;IAClBV,QAAQC;IACRE;EACF;AAEA,QAAMQ,gBAAgBC,4BAA4Bb,aAAac,eAAe,CAAA,GAAIT,KAAAA;AAClFA,QAAMG,QAAQ,MAAMP,OAAOc,KAAKb,WAAWU,aAAAA;AAC3C,MAAIT,OAAO;AACTE,UAAMF,QAAQA;EAChB;AAEA,SAAO;IACLW,aAAad,aAAac;IAC1BE,QAAQ;SAAKhB,aAAagB,UAAU,CAAA;MAAKX;;EAC3C;AACF;;;ACxCA,SAASY,mBAAAA,wBAAuB;AAOzB,IAAMC,qBAAqB,OAAOC,iBAAAA;AACvC,QAAMC,SAAmB,CAAA;AAGzB,QAAMC,2BAA2B,MAAMC,QAAQC,IAC7CJ,aAAaK,aAAaC,IAAI,CAACC,eAAeC,iBAAiBD,UAAAA,CAAAA,KAAgB,CAAA,CAAE;AAEnF,aAAWE,gBAAgBP,0BAA0B;AACnD,QAAIO,aAAaC,SAAS,QAAQ;AAChCT,aAAOU,KAAI,GAAIF,aAAaR,MAAM;IACpC;EACF;AAGA,QAAMW,oBAAoB,MAAMT,QAAQC,IACtCJ,aAAaa,QAAQP,IAAI,OAAOQ,UAAAA;AAC9B,UAAMC,oBAAoB,MAAMC,wBAAwBhB,cAAcc,KAAAA;AACtE,QAAIC,kBAAkBL,SAAS,QAAQ;AACrC,aAAOK;IACT;AACA,UAAME,wBAAwB,MAAMC,4BAA4BlB,cAAcc,KAAAA;AAC9E,QAAIG,sBAAsBP,SAAS,QAAQ;AACzC,aAAOO;IACT;AACA,WAAO;MAAEP,MAAM;IAAO;EACxB,CAAA,KAAM,CAAA,CAAE;AAEV,aAAWD,gBAAgBG,mBAAmB;AAC5C,QAAIH,aAAaC,SAAS,QAAQ;AAChCT,aAAOU,KAAI,GAAIF,aAAaR,MAAM;IACpC;EACF;AAEA,MAAIA,OAAOkB,WAAW,GAAG;AACvB,WAAO;MAAET,MAAM;IAAO;EACxB;AACA;AACE,WAAO;MACLA,MAAM;MACNT;IACF;EACF;AACF;AAEO,IAAMe,0BAA0B,OACrChB,cACAc,UAAAA;AAEA,aAAWP,cAAcP,aAAaK,eAAe,CAAA,GAAI;AACvD,QAAI,CAACE,WAAWa,OAAOC,OAAOP,MAAMQ,MAAM,GAAG;AAC3C,UAAI,CAACR,MAAMS,OAAO;AAChB,eAAO;UACLb,MAAM;UACNT,QAAQ;YAAC;;QACX;MACF;AAEA,YAAMc,oBAAoB,MAAMS,YAAYV,MAAMS,OAAOhB,WAAWkB,QAAQC,IAAIZ,MAAMQ,MAAM;AAC5F,UAAIP,kBAAkBL,SAAS,QAAQ;AACrC,eAAOK;MACT;IACF;EACF;AAEA,SAAO;IAAEL,MAAM;EAAO;AACxB;AAMO,IAAMQ,8BAA8B,OACzClB,cACAc,UAAAA;AAEA,MAAIA,MAAMa,SAASC,wBAAwB;AACzC,WAAO;MACLlB,MAAM;MACNT,QAAQ;QAAC,2BAA2Ba,MAAMa,IAAI;;IAChD;EACF;AAEA,QAAME,WAAWC,4BAA4B9B,aAAaK,eAAe,CAAA,GAAIS,KAAAA;AAC7E,MAAI,CAAE,MAAMiB,iBAAgBjB,MAAMQ,QAAQO,UAAUf,MAAMkB,KAAK,GAAI;AACjE,WAAO;MAAEtB,MAAM;MAAQT,QAAQ;QAAC;;IAAqB;EACvD;AAEA,SAAO;IAAES,MAAM;EAAO;AACxB;;;AC/FA,SAASuB,mBAAmBC,oBAAoB;AAChD,SAASC,eAAe;AACxB,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AAEpB,SAA0BC,eAAAA,oBAAmB;AAE7C,SAA6BC,YAAAA,WAAUC,cAAAA,aAAYC,cAAAA,mBAAkB;;;ACPrE,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,aAAAA,kBAAiB;AAE1B,SAA6BC,UAAUC,cAAAA,mBAAkB;;AAoBlD,IAAMC,mBAAN,MAAMA;;EACHC,SAAS,IAAIC,YAAgCC,WAAUC,IAAI;EAE1DC,iBAAiB,IAAIC,SAAAA;EAE9B,YAA6BC,WAAsB;SAAtBA,YAAAA;EAAuB;EAEpD,IAAIC,QAA0C;AAC5C,WAAO,KAAKP;EACd;;;;;;;EAQA,MAAMQ,QAAQC,YAAwBC,UAAoC;AACxE,UAAMC,YAAYC,uBAAuBH,UAAAA;AACzCI,IAAAA,WAAUF,UAAU,OAAA,MAAa,sCAAA,QAAA;;;;;;;;;AACjCE,IAAAA,WAAUF,UAAUG,SAASC,OAAO,KAAKT,SAAS,GAAA,QAAA;;;;;;;;;AAElD,UAAMU,OAAiB;MACrBC,KAAKR,WAAWS,QAAQC;MACxBV;MACAE;MACAS,QAAQV;IACV;AAEA,SAAKV,OAAOqB,IAAIZ,WAAWS,QAAQC,IAAIH,IAAAA;AACvC,UAAM,KAAKZ,eAAekB,UAAUN,IAAAA;EACtC;AACF;;;ACvDA,SAASO,aAAAA,kBAAiB;AAG1B,SAA6BC,YAAAA,WAAUC,cAAAA,aAAYC,kBAAkB;AAa9D,IAAMC,yBAAN,MAAMA;EACMC,eAAe,IAAIC,YAA+CC,WAAUC,IAAI;EAChFC,mCAAmC,IAAIC,WAAWH,WAAUC,IAAI;EAChEG,oCAAoC,IAAID,WAAWH,WAAUC,IAAI;EAEzEI,wBAAwB,IAAIC,UAAAA;EAC5BC,+BAA+B,IAAID,UAAAA;EAE5C,IAAIE,cAA+D;AACjE,WAAO,KAAKV;EACd;EAEA,MAAMW,QAAQC,YAAuC;AACnD,UAAMC,eAAeD,WAAWE;AAChC,QAAID,gBAAgB,MAAM;AACxB;IACF;AACA,UAAME,YAAYC,uBAAuBJ,UAAAA;AACzC,YAAQG,UAAU,OAAA,GAAQ;MACxB,KAAK,mDAAmD;AACtD,aAAKT,kCAAkCW,IAAIF,UAAUF,YAAY;AACjE,cAAMK,qBAAqB,KAAKlB,aAAamB,IAAIJ,UAAUF,YAAY;AACvE,YAAIK,sBAAsB,MAAM;AAC9B,eAAKlB,aAAaoB,OAAOL,UAAUF,YAAY;AAC/C,gBAAM,KAAKJ,6BAA6BY,UAAU;YAChDR,cAAcE,UAAUF;YACxBS,YAAYJ;UACd,CAAA;QACF;AACA;MACF;MACA,KAAK,iDAAiD;AACpD,YAAIN,WAAWE,IAAI;AACjB,gBAAMS,YAAYR,UAAUS,aAAaT,UAAUS,UAAUC,QAAO,IAAKC,KAAKC,IAAG;AACjF,gBAAMC,UAAU,KAAKxB,iCAAiCyB,IAAIjB,WAAWE,EAAE,KAAK,CAACC,UAAUe;AACvF,gBAAMC,eAAe,KAAKzB,kCAAkCuB,IAAIjB,WAAWE,EAAE;AAC7E,cAAIS,aAAaQ,gBAAgBH,SAAS;AACxC;UACF;AACA,gBAAMN,aAAsC;YAAE,GAAGP;UAAU;AAC3D,eAAKf,aAAagC,IAAIpB,WAAWE,IAAIQ,UAAAA;AACrC,gBAAM,KAAKf,sBAAsBc,UAAU;YACzCR,cAAcD,WAAWE;YACzBQ;UACF,CAAA;QACF;AACA;MACF;MACA,KAAK,qCAAqC;AACxC,YAAIP,UAAUkB,0BAA0B,MAAM;AAC5C,eAAK7B,iCAAiCa,IAAIF,UAAUkB,sBAAsB;AAC1E,gBAAMf,qBAAqB,KAAKlB,aAAamB,IAAIJ,UAAUkB,sBAAsB;AACjF,cAAIf,sBAAsB,QAAQ,CAACA,mBAAmBY,UAAU;AAC9D,iBAAK9B,aAAaoB,OAAOL,UAAUkB,sBAAsB;AACzD,kBAAM,KAAKxB,6BAA6BY,UAAU;cAChDR,cAAcE,UAAUkB;cACxBX,YAAYJ;YACd,CAAA;UACF;QACF;AACA;MACF;IACF;EACF;AACF;;;AChFA,SAASgB,aAAAA,kBAAiB;AAC1B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AACpB,SAAgDC,eAAAA,oBAAmB;AACnE,SAASC,cAAAA,mBAAkB;;;ACJ3B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,WAAW;AAEpB,SAA6BC,YAAAA,WAAUC,cAAAA,aAAYC,cAAAA,mBAAkB;;AAE9D,IAAMC,kBAAN,MAAMA;;;;;EAIHC,qBAAqB;;;;EAIrBC,QAAQ;IAAEC,IAAI;IAAIC,SAAS,CAAA;IAAIC,UAAU,CAAA;EAAG;;;;;EAK5CC,YAAY;IAAEH,IAAI;IAAIC,SAAS,CAAA;IAAIC,UAAU,CAAA;EAAG;;;;EAIhDE,wBAAwB,IAAIT,YAAsCH,WAAUa,IAAI;;;;EAIhFC,mBAAmB,IAAIX,YAAsCH,WAAUa,IAAI;EAC3EE,kBAAkB,IAAIZ,YAA6BH,WAAUa,IAAI;EAElEG,wBAAwB,IAAId,UAAAA;EAEnC,YAA6Be,eAAsD;SAAtDA,gBAAAA;EAAuD;EAE7EC,gBAAgBC,WAAyC;AAC9D,WAAO,KAAKJ,gBAAgBK,IAAID,SAAAA;EAClC;EAEOE,WAA0C;AAC/C,WAAO,KAAKN;EACd;EAEOO,aAA0B;AAC/B,WAAO,KAAKX,UAAUF,QAAQc,IAAI,CAACC,MAAMA,EAAEC,WAAYjB,EAAE;EAC3D;EAEOkB,sBAAqC;AAC1C,WAAO;MAAEC,OAAO,KAAKb;IAAiB;EACxC;EAEOc,UAAUH,YAAwBI,WAA6B;AACpE,UAAMC,YAA4B;MAChCtB,IAAI,KAAKF;MACTmB;MACAI;MACApB,SAAS,CAAA;MACTC,UAAU,CAAA;IACZ;AACA,SAAKE,sBAAsBmB,IAAIN,WAAWjB,IAAKsB,SAAAA;AAC/C,UAAME,YAAYP,WAAWQ,uBAAuB,CAAA;AACpD,QAAID,UAAUE,WAAW,GAAG;AAC1B,WAAK3B,MAAMG,SAASyB,KAAKL,SAAAA;AACzBA,gBAAUrB,QAAQ0B,KAAK,KAAK5B,KAAK;IACnC,OAAO;AACL,iBAAW6B,YAAYJ,WAAW;AAChC,cAAMK,eAAe,KAAKzB,sBAAsBQ,IAAIgB,QAAAA;AACpD,YAAIC,gBAAgB,MAAM;AACxBpC,cAAIqC,MAAM,oDAAoD;YAAEb;YAAYW;UAAS,GAAA;;;;;;AACrF;QACF;AACAC,qBAAa3B,SAASyB,KAAKL,SAAAA;AAC3BA,kBAAUrB,QAAQ0B,KAAKE,YAAAA;AACvB,aAAKE,0BAA0BF,YAAAA;MACjC;IACF;AACAP,cAAUpB,SAASyB,KAAK,KAAKxB,SAAS;AACtC,SAAKA,UAAUF,QAAQ0B,KAAKL,SAAAA;AAC5B,WAAO,KAAKU,kBAAkBV,SAAAA;EAChC;EAEQS,0BAA0BE,QAA8B;AAC9D,UAAMC,cAAcD,OAAO/B,SAASiC,QAAQ,KAAKhC,SAAS;AAC1D,QAAI+B,eAAe,GAAG;AACpBD,aAAO/B,SAASkC,OAAOF,aAAa,CAAA;AACpC,YAAMG,sBAAsB,KAAKlC,UAAUF,QAAQkC,QAAQF,MAAAA;AAC3D1C,MAAAA,WAAU8C,uBAAuB,GAAA,QAAA;;;;;;;;;AACjC,WAAKlC,UAAUF,QAAQmC,OAAOC,qBAAqB,CAAA;IACrD;EACF;EAEA,MAAcL,kBAAkBV,WAA0C;AACxE,UAAM,EAAEL,YAAYI,UAAS,IAAKC;AAClC/B,IAAAA,WAAU0B,YAAAA,QAAAA;;;;;;;;;AACV,QAAIqB,kBAA2B,CAAA;AAC/B,UAAMC,yCAAyC,KAAKpC,UAAUF,QAAQyB,WAAW;AACjF,QAAIa,wCAAwC;AAC1C,YAAM5B,YAAYM,WAAWuB,QAAQxC;AACrC,UAAI,KAAKS,cAAcgC,gBAAgB,KAAKvB,oBAAmB,GAAID,YAAYI,SAAAA,GAAY;AACzF,cAAMqB,kBAAkB,KAAKjC,cAAckC,YAAY1B,YAAYK,UAAUD,SAAS;AACtF,cAAMuB,mBAAmB,KAAKrC,gBAAgBK,IAAID,SAAAA;AAClD,aAAKJ,gBAAgBgB,IAAIZ,WAAW+B,eAAAA;AACpC,aAAKpC,iBAAiBiB,IAAIZ,WAAWW,SAAAA;AACrC,YAAI,KAAKb,cAAcoC,gBAAgBH,iBAAiBE,gBAAAA,GAAmB;AACzEN,0BAAgBX,KAAKe,eAAAA;QACvB;MACF;IACF,OAAO;AACLJ,wBAAkB,KAAKQ,gBAAe;IACxC;AACA,QAAIR,gBAAgBZ,SAAS,GAAG;AAC9B,YAAM,KAAKlB,sBAAsBuC,UAAUT,eAAAA;IAC7C;EACF;;;;;;;EAQQQ,kBAA2B;AAEjC,UAAME,eAAe,oBAAIC,IAAAA;AACzB,UAAMC,QAAwB;MAAC,KAAKC,gBAAe;;AACnD,QAAIC,WAAgC;AACpC,WAAOA,YAAY,MAAM;AACvB,YAAMC,OAAOH,MAAMI,IAAG;AACtB7D,UAAI,gBAAgB;QAAEO,IAAIqD,KAAKE,KAAKvD;MAAG,GAAA;;;;;;AACvC,WAAKwD,iBAAiBH,IAAAA;AACtB,YAAMI,iBAAiB,KAAKC,kBAAkBR,OAAOF,cAAcK,IAAAA;AACnE,UAAII,kBAAkB,MAAM;AAC1BhE,YAAI,2BAAA,QAAA;;;;;;AACJ;MACF;AACA,YAAMkE,cAAc,KAAKC,YAAYH,cAAAA;AACrC,UAAIE,YAAYE,SAAS,mBAAmB;AAC1C,aAAKC,mBAAmBZ,OAAOF,cAAcW,aAAaF,cAAAA;AAC1D;MACF;AACA,YAAMM,SAASJ,YAAYN;AAC3B,UAAIU,OAAOR,KAAKrD,SAASwB,WAAW,GAAG;AACrC0B,mBAAWW;MACb,WAAWA,OAAOR,KAAKrD,SAASwB,WAAW,GAAG;AAC5CqC,eAAOR,OAAOQ,OAAOR,KAAKrD,SAAS,CAAA;AACnCgD,cAAMvB,KAAKoC,MAAAA;MACb,OAAO;AACL,aAAKC,eAAed,OAAOa,MAAAA;MAC7B;IACF;AACA,QAAIb,MAAMxB,SAAS,GAAG;AACpBjC,UAAIqC,MAAM,oDAAoD;QAC5DoB,OAAOA,MAAMnC,IAAI,CAACkD,OAAO;UAAEZ,MAAMa,aAAaD,CAAAA;UAAIV,MAAMU,EAAEV,KAAKvD;QAAG,EAAA;MACpE,GAAA;;;;;;IACF;AACA,WAAO,KAAKmE,iBAAiBf,QAAAA;EAC/B;EAEQU,mBACNZ,OACAF,cACAW,aACAF,gBACM;AACNP,UAAMvB,KAAI,GACLgC,YAAYS,OAAOrD,IAAI,CAACsC,SAAAA;AACzB,YAAMgB,iBAAiBhB,KAAKgB,kBAAkB,IAAI1E,YAAsCH,WAAUa,IAAI;AACtGsD,kBAAYU,eAAeC,QAAQ,CAACC,OAAOC,QAAQH,eAAe9C,IAAIiD,KAAKD,KAAAA,CAAAA;AAC3E,aAAO;QAAE,GAAGZ,YAAYc;QAAMC,YAAYrB,KAAKqB;QAAYL;MAAe;IAC5E,CAAA,CAAA;AAEF5E,QAAI,gBAAgB,OAAO;MACzBkF,OAAOzB,MAAMxB;MACbwB,OAAOA,MAAMnC,IAAI,CAACsC,UAAU;QAC1BoB,MAAMd,YAAYc,KAAKlB,KAAKvD;QAC5BqD,MAAMa,aAAab,IAAAA;QACnBuB,WAAWvB,MAAMgB,gBAAgBQ,UAAU,CAAC7D,MAAM,KAAKP,cAAcqE,YAAY9D,EAAEK,SAAS,CAAA;MAC9F,EAAA;IACF,IAAA;;;;;;AACA,UAAM0D,iBAAiBtB,eAAeuB,OAAO,CAACC,MAAM,CAACtB,YAAYS,OAAOc,SAASD,CAAAA,CAAAA;AACjFjC,iBAAazB,IAAIkC,eAAe,CAAA,EAAGF,KAAKvD,IAAI+E,cAAAA;EAC9C;EAEQrB,kBACNR,OACAF,cACAK,MACuB;AACvB,UAAM8B,cAAcnC,aAAapC,IAAIyC,KAAKE,KAAKvD,EAAE,KAAK,CAAA;AACtDgD,iBAAazB,IAAI8B,KAAKE,KAAKvD,IAAImF,WAAAA;AAC/BA,gBAAYxD,KAAK0B,IAAAA;AACjB,QAAI8B,YAAYzD,SAAS2B,KAAKE,KAAKtD,QAAQyB,QAAQ;AACjD,aAAO;IACT;AACA,QAAI2B,KAAKE,KAAKvD,OAAO,KAAKG,UAAUH,MAAMkD,MAAMxB,SAAS,GAAG;AAC1DjC,UAAI,gEAAA,QAAA;;;;;;AACJ,aAAO;IACT;AACAuD,iBAAaoC,OAAO/B,KAAKE,KAAKvD,EAAE;AAChC,WAAOmF;EACT;EAEQ3B,iBAAiBH,MAA0B;AACjD,UAAMgC,iBAAiBhC,KAAKE,KAAKtC;AACjC,QAAIoE,kBAAkB,MAAM;AAC1B;IACF;AACA,UAAMC,iBAAiBD,eAAe7C,QAAQxC;AAC9CqD,SAAKkC,YAAYC,IAAIH,eAAerF,EAAE;AACtC,QAAIyC,kBAAkB,KAAKhC,cAAcgC,gBAAgBY,MAAMgC,gBAAgBhC,KAAKE,KAAKlC,SAAS;AAElG,QAAI,CAACoB,mBAAmBY,KAAKE,KAAKtD,QAAQ,CAAA,GAAID,OAAO,KAAKD,MAAMC,IAAI;AAClE,YAAMyF,cAAc,KAAKvE,oBAAmB;AAC5CuB,wBAAkB,KAAKhC,cAAcgC,gBAAgBgD,aAAaJ,gBAAgBhC,KAAKE,KAAKlC,SAAS;IACvG;AACA,QAAIoB,iBAAiB;AACnBY,WAAKqC,oBAAoBF,IAAIF,cAAAA;AAC7BjC,WAAKsC,YAAYH,IAAIH,eAAeO,MAAM;AAC1CvC,WAAKlC,MAAMI,IAAI+D,gBAAgBjC,KAAKE,IAAI;AACxC9D,UAAI,sBAAsB,OAAO;QAC/B+C,SAAS8C;QACTO,UAAU,KAAKpF,cAAcqE,YAAYzB,KAAKE,KAAKlC,SAAS;MAC9D,IAAA;;;;;;IACF;EACF;EAEQ2C,eAAed,OAAuBG,MAA0B;AACtE,UAAMyC,eAAezC,KAAKqB,aAAarB,KAAKE,KAAKvD,EAAE;AACnD,UAAM+F,UAAUD,gBAAgBzC,KAAKE,KAAKrD;AAC1C,eAAW8F,UAAUD,SAAS;AAC5BtG,UAAI,kBAAkB;QAAEgF,MAAMpB,KAAKE,KAAKvD;QAAIiG,IAAID,OAAOhG;MAAG,GAAA;;;;;;AAC1D,YAAMkG,OAAqB;QACzBC,WAAW9C;QACXqB,YAAY;UAAE,GAAGrB,KAAKqB;UAAY,CAACrB,KAAKE,KAAKvD,EAAE,GAAG;YAACgG;;QAAQ;QAC3DzC,MAAMyC;QACNT,aAAa,IAAI3F,YAAWJ,WAAUa,MAAMgD,KAAKkC,WAAW;QAC5DpE,OAAO,IAAIxB,YAAWH,WAAUa,MAAM;aAAIgD,KAAKlC,MAAMiF,QAAO;SAAG;QAC/DT,aAAa,IAAI/F,YAAWJ,WAAUa,IAAI;QAC1CqF,qBAAqB,IAAI9F,YAAWJ,WAAUa,IAAI;QAClDgE,gBAAgBhB,KAAKgB;MACvB;AACAnB,YAAMvB,KAAKuE,IAAAA;IACb;EACF;;;;;EAMQ/B,iBAAiBd,MAA6B;AACpD,UAAMf,kBAA2B,CAAA;AACjC,UAAM+D,cAAc,IAAI1G,YAA6BH,WAAUa,IAAI;AACnE,UAAMiG,eAAe,IAAI3G,YAAsCH,WAAUa,IAAI;AAC7E,eAAW,CAACkG,YAAYC,aAAAA,KAAkBnD,KAAKlC,MAAMiF,QAAO,GAAI;AAC9D,YAAMP,WAAW,KAAKpF,cAAckC,YAAY6D,cAAcvF,YAAauF,cAAcnF,SAAS;AAClG,YAAMoF,YAAY,KAAKlG,gBAAgBK,IAAI2F,UAAAA;AAC3CF,kBAAY9E,IAAIgF,YAAYV,QAAAA;AAC5BS,mBAAa/E,IAAIgF,YAAYC,aAAAA;AAC7B,UAAI,KAAK/F,cAAcoC,gBAAgBgD,UAAUY,SAAAA,GAAY;AAC3DnE,wBAAgBX,KAAKkE,QAAAA;MACvB;IACF;AACA,SAAKtF,kBAAkB8F;AACvB,SAAK/F,mBAAmBgG;AACxB,WAAOhE;EACT;;;;;;EAOQoE,qBAAqBxD,OAAqC;AAChE,UAAMyD,mBAAmBzD,MAAM0D,OAAO,CAACC,KAAKxD,SAAAA;AAC1C,UAAIyD,KAAKzD,KAAK8C;AACd,aAAOW,IAAI;AACTD,YAAItF,IAAIuF,GAAGvD,KAAKvD,IAAI8G,EAAAA;AACpBA,aAAKA,GAAGX;MACV;AACA,aAAOU;IACT,GAAG,oBAAI5D,IAAAA,CAAAA;AACP,QAAI8D,QAAQ,KAAKhH,MAAMC;AACvB,QAAIgH,WAAgC;AACpC,eAAW,CAAChH,IAAImB,KAAAA,KAAUwF,iBAAiBP,QAAO,GAAI;AACpD,YAAMf,iBAAiBlE,MAAMoC,KAAKtC;AAClC,UAAIoE,kBAAkB,MAAM;AAC1B,cAAM4B,qBAAqB/D,MAAMgE,MAAM,CAACjD,MAAMA,EAAEsB,YAAY4B,IAAI9B,eAAerF,EAAE,CAAA;AACjF,YAAIiH,sBAAsBjH,KAAK+G,OAAO;AACpCA,kBAAQ/G;AACRgH,qBAAW7F;QACb;MACF;IACF;AACA,WAAO6F,YAAY,KAAK7D,gBAAe;EACzC;;;;;;EAOQiE,mBAAmBjB,WAAyB9C,MAAkC;AACpF,UAAMgE,oBAAoBhE,KAAKqB,WAAWyB,UAAU5C,KAAKvD,EAAE,KAAK,QAAQqD,KAAK8C,aAAa;AAC1F,QAAIkB,mBAAmB;AACrB,aAAOhE;IACT;AACA,QAAI8C,UAAU5C,KAAKvD,OAAOqD,KAAK8C,WAAW5C,KAAKvD,IAAI;AACjD,aAAOqD;IACT;AACA,QAAIyD,KAAKzD,KAAK8C;AACd,WAAOW,GAAGvD,KAAKvD,OAAOmG,UAAU5C,KAAKvD,IAAI;AACvC8G,SAAGnB,YAAYrB,QAAQ,CAACgD,QAAQjE,KAAKsC,YAAYH,IAAI8B,GAAAA,CAAAA;AACrDR,SAAGpB,oBAAoBpB,QAAQ,CAACiD,MAAMlE,KAAKqC,oBAAoBF,IAAI+B,CAAAA,CAAAA;AACnET,WAAKA,GAAIX;AACT9C,WAAK8C,YAAYW;IACnB;AACA,WAAOzD;EACT;EAEQO,YAAYH,gBAAoD;AACtElE,IAAAA,WAAUkE,eAAe/B,UAAU,GAAA,QAAA;;;;;;;;;AACnC,QAAI+B,eAAe/B,WAAW,GAAG;AAC/B,aAAO;QAAEmC,MAAM;QAAUR,MAAMI,eAAe,CAAA;MAAG;IACnD;AACA,UAAM0C,YAAY,KAAKO,qBAAqBjD,cAAAA;AAC5ChE,QAAI,iBAAiB,OAAO;MAC1B+H,aAAarB,UAAU5C,KAAKvD;MAC5ByH,WAAWhE,eAAe/B;MAC1BgG,YAAYjE,eAAe1C,IAAI,CAAC4G,OAAOA,GAAGxB,WAAW5C,KAAKvD,EAAAA;IAC5D,IAAA;;;;;;AACA,UAAMkD,QAAQO,eAAe1C,IAAI,CAACkD,MAAM,KAAKmD,mBAAmBjB,WAAWlC,CAAAA,CAAAA;AAC3E1E,IAAAA,WAAU4G,WAAAA,QAAAA;;;;;;;;;AACV,UAAMyB,SAAuB;MAC3BzB,WAAWA,UAAUA;MACrBzB,YAAY;QAAE,GAAGyB,UAAUzB;QAAY,CAACyB,UAAU5C,KAAKvD,EAAE,GAAG,CAAA;MAAG;MAC/DqE,gBAAgB8B,UAAU9B;MAC1BkB,aAAa,IAAI3F,YAAWJ,WAAUa,MAAM8F,UAAUZ,WAAW;MACjEI,aAAa,IAAI/F,YAAWJ,WAAUa,MAAM8F,UAAUR,WAAW;MACjED,qBAAqB,IAAI9F,YAAWJ,WAAUa,MAAM8F,UAAUT,mBAAmB;MACjFvE,OAAOgF,UAAUhF,MAAM0D,UAAU,CAAC7D,MAAMA,CAAAA;MACxCuC,MAAML,MAAM,CAAA,EAAGK;IACjB;AACA,UAAMsE,kBAAkB,IAAIlI,YAAoCH,WAAUa,IAAI;AAC9E,eAAWgD,QAAQH,OAAO;AACxBzD,UAAI,qBAAqB,OAAO;QAC9BsG,SAAS7B,aAAab,IAAAA;QACtByE,UAAUzE,KAAKqC;QACfC,aAAatC,KAAKsC;QAClBxE,OAAOkC,KAAKlC,MAAM0D,UAAU,CAAC7D,MAAM,KAAKP,cAAcqE,YAAY9D,EAAEK,SAAS,CAAA;MAC/E,IAAA;;;;;;AACAgC,WAAKsC,YAAYrB,QAAQ,CAACgD,QAAQM,OAAOjC,YAAYH,IAAI8B,GAAAA,CAAAA;AACzDjE,WAAKkC,YAAYjB,QAAQ,CAACyD,SAASH,OAAOrC,YAAYC,IAAIuC,IAAAA,CAAAA;AAC1DH,aAAOlD,WAAYyB,UAAU5C,KAAKvD,EAAE,EAAE2B,KAAI,GAAK0B,KAAKqB,WAAYyB,UAAU5C,KAAKvD,EAAE,KAAK,CAAA,CAAE;AACxF,iBAAWgI,mBAAmB3E,KAAKqC,qBAAqB;AACtD,cAAMuC,iBAAiBJ,gBAAgBjH,IAAIoH,eAAAA;AAC3C,YAAIC,kBAAkB,QAAQ,KAAKC,0BAA0BD,gBAAgB5E,MAAM2E,eAAAA,GAAkB;AACnGH,0BAAgBtG,IAAIyG,iBAAiB3E,IAAAA;QACvC;MACF;IACF;AACA,UAAM8E,cAAc,oBAAIC,IAAAA;AACxB,UAAMC,gBAAgBF,YAAY3C,IAAI8C,KAAKH,WAAAA;AAC3C,eAAW,CAAC3F,SAAS+F,MAAAA,KAAWV,gBAAgBzB,QAAO,GAAI;AACzDwB,aAAOlC,oBAAoBF,IAAIhD,OAAAA;AAC/B,YAAMP,SAASsG,OAAOpH,MAAMP,IAAI4B,OAAAA;AAChCoF,aAAOzG,MAAMI,IAAIiB,SAASP,MAAAA;AAC1BxC,UAAI,qBAAqB,OAAO;QAAE+C;QAASrB,OAAO,KAAKV,cAAcqE,YAAY7C,OAAOZ,SAAS;MAAE,IAAA;;;;;;AACnG,YAAMmH,aAAatF,MAAM8B,OAAO,CAACf,MAAMA,MAAMsE,MAAAA;AAC7C,WAAK9H,cAAcgI,oBAAoBD,YAAYvG,MAAAA,EAAQqC,QAAQ+D,aAAAA;IACrE;AACA,QAAIF,YAAYO,OAAO,GAAG;AACxB,aAAO;QACL7E,MAAM;QACNO,QAAQ;aAAI+D,YAAYQ,OAAM;;QAC9BlE,MAAM0B;QACN9B,gBAAgBwD,gBAAgBhD,UAAU,CAAC7D,GAAGwD,QAAQxD,EAAEG,MAAMP,IAAI4D,GAAAA,CAAAA;MACpE;IACF;AACA,WAAO;MAAEX,MAAM;MAAUR,MAAMuE;IAAO;EACxC;;;;;;;;;;;EAYQM,0BACNU,UACAC,WACAb,iBACS;AACT,UAAMc,kBAAkBD,UAAU1H,MAAMP,IAAIoH,eAAAA;AAC5C,UAAMe,gBAAgBH,SAASzH,MAAMP,IAAIoH,eAAAA;AACzC,QAAIc,gBAAgB9I,OAAO+I,cAAc/I,IAAI;AAC3C,aAAO;IACT;AAEA,UAAMgJ,eAAeJ,SAASrF,KAAKvD;AACnC,QAAI8I,gBAAgB9I,OAAOgJ,gBAAgBD,cAAc/I,OAAOgJ,cAAc;AAC5EvJ,UAAI,uCAAuC;QAAEuJ,cAAcJ,SAASrF,KAAKvD;MAAG,GAAA;;;;;;AAC5E,aAAOgJ,iBAAiBF,gBAAgB9I;IAC1C;AACA,UAAMiJ,sBAAsBH,gBAAgB7H;AAC5C,UAAMiI,oBAAoBH,cAAc9H;AAExC,QAAI2H,SAASrD,YAAY4B,IAAI8B,oBAAoBjJ,EAAE,MAAO6I,UAAUtD,YAAY4B,IAAI+B,kBAAkBlJ,EAAE,GAAI;AAC1GP,UAAI,2DAA2D;QAC7D0J,SAASJ,cAAc/I;QACvB6I,WAAWC,gBAAgB9I;MAC7B,GAAA;;;;;;AACA,aAAO6I,UAAUtD,YAAY4B,IAAI+B,kBAAkBlJ,EAAE;IACvD;AAEA,UAAMoJ,oBAAoB,KAAK3I,cAAc4I,qBAC3CT,UACAM,mBACAL,WACAI,mBAAAA;AAEF,QAAIG,qBAAqB,MAAM;AAC7B,aAAOA,sBAAsBH;IAC/B;AACA,QAAIJ,UAAUlD,YAAY+C,SAASE,SAASjD,YAAY+C,MAAM;AAC5DjJ,UAAI,+CAA+C;QACjD6J,aAAa;UAACV,SAASjD,YAAY+C;UAAMG,UAAUlD,YAAY+C;;MACjE,GAAA;;;;;;AACA,aAAOG,UAAUlD,YAAY+C,OAAOE,SAASjD,YAAY+C;IAC3D;AACAjJ,QAAI,uCAAA,QAAA;;;;;;AACJ,WAAOwJ,oBAAoBM,aAAaC,QAAO,IAAKN,kBAAkBK,aAAaC,QAAO;EAC5F;EAEQrG,kBAAgC;AACtC,WAAO;MACLI,MAAM,KAAKxD;MACX2E,YAAY,CAAC;MACbiB,aAAa,IAAI/F,YAAWJ,WAAUa,IAAI;MAC1CqF,qBAAqB,IAAI9F,YAAWJ,WAAUa,IAAI;MAClDc,OAAO,IAAIxB,YAAsCH,WAAUa,IAAI;MAC/DkF,aAAa,IAAI3F,YAAWJ,WAAUa,IAAI;IAC5C;EACF;AACF;AAwGA,IAAM6D,eAAe,CAAIb,SAAAA;AACvB,SAAOoG,OAAOC,YAAYD,OAAOrD,QAAQ/C,KAAKqB,UAAU,EAAG3D,IAAI,CAAC,CAAC4I,GAAGC,EAAAA,MAAQ;IAACD;IAAGC,GAAG7I,IAAI,CAACC,MAAMA,EAAEhB,EAAE;GAAE,CAAA;AACtG;;;;AD7gBO,IAAM6J,qBAAN,MAAMA;;EACHC;EACAC,kBAAkB,IAAIC,YAAmDC,WAAUC,IAAI;EACvFC,aAAa,IAAIC,gBAAyC,IAAI;EAE7DC,sBAAsB,KAAKF,WAAWG;EAE/C,YAA6BC,WAAsB;SAAtBA,YAAAA;EAAuB;EAEpD,IAAIC,UAAkC;AACpC,WAAO,KAAKV,aAAa,KAAKK,WAAWM,gBAAgB,KAAKX,SAAS;EACzE;EAEA,IAAIY,UAA8C;AAChD,WAAO,KAAKP,WAAWQ,SAAQ;EACjC;EAEA,IAAIC,uBAAoC;AACtC,WAAO,KAAKT,WAAWU,WAAU;EACnC;EAEAC,QAAQC,QAAqC;AAC3C,WAAO,KAAKC,SAAS,KAAKb,WAAWc,oBAAmB,GAAIF,MAAAA;EAC9D;;;;;EAMA,MAAMG,QAAQC,YAAuC;AACnD,UAAMC,YAAYC,uBAAuBF,UAAAA;AAEzC,YAAQC,UAAU,OAAA,GAAQ;MACxB,KAAK,qCAAqC;AACxCE,QAAAA,WAAUF,UAAUG,SAASC,OAAO,KAAKjB,SAAS,GAAA,QAAA;;;;;;;;;AAClD,YAAI,KAAKT,aAAa,QAAQqB,WAAWM,WAAW,KAAKlB,WAAW;AAClE,eAAKT,YAAYqB,WAAWO,QAAQC;QACtC;AACA,YAAIP,UAAUQ,WAAW,MAAM;AAC7B,eAAK7B,gBAAgB8B,IAAIV,WAAWO,QAAQC,IAAIP,UAAUQ,OAAO;QACnE;AACA,cAAM,KAAKzB,WAAW2B,UAAUX,YAAYC,SAAAA;AAC5C;MACF;MACA,KAAK,uCAAuC;AAC1C,cAAML,SAAS,KAAKZ,WAAWM,gBAAgBU,WAAWO,QAAQC,EAAE;AACpE,YAAIZ,QAAQ;AACVA,iBAAOa,UAAUR,UAAUQ;QAC7B,OAAO;AACLG,UAAAA,KAAIC,KAAK,oBAAoB;YAAEL,IAAIR,WAAWO,QAAQC;UAAG,GAAA;;;;;;QAC3D;AACA,aAAK5B,gBAAgB8B,IAAIV,WAAWO,QAAQC,IAAIP,UAAUQ,OAAO;AACjE;MACF;MACA;AACE,cAAM,IAAIK,MAAM,wBAAA;IACpB;EACF;EAEOC,YAAYf,YAAwBC,WAAoC;AAC7E,UAAMe,YAAYhB,WAAWO,QAAQC;AACrC,WAAO;MACLS,KAAKD;MACLE,MAAMjB,UAAUiB;MAChBlB;MACAC;MACAQ,SAAS,KAAK7B,gBAAgBuC,IAAIH,SAAAA;IACpC;EACF;EAEOI,gBAAgBC,OAAgCrB,YAAwBC,WAAiC;AAC9G,QAAIA,UAAUiB,SAASI,aAAYC,KAAKC,OAAO;AAC7C,aAAOxB,WAAYM,OAAOD,OAAO,KAAKjB,SAAS;IACjD;AACA,UAAMkB,SAASN,WAAWM;AAC1B,UAAMmB,oBAAoBnB,OAAOD,OAAOL,WAAWO,QAAQC,EAAE;AAC7D,QAAIiB,mBAAmB;AACrB,aAAO;IACT;AACA,QAAInB,OAAOD,OAAOJ,UAAUG,QAAQ,GAAG;AACrC,aAAO;IACT;AACA,UAAMsB,aAAa,KAAK7B,SAASwB,OAAOf,MAAAA;AACxC,WAAOoB,eAAeJ,aAAYC,KAAKI,SAASD,eAAeJ,aAAYC,KAAKC;EAClF;EAEOI,oBACLC,OACAC,QAC0B;AAE1B,QAAIA,OAAO7B,UAAUiB,SAASI,aAAYC,KAAKQ,WAAWD,OAAO7B,UAAUiB,SAASI,aAAYC,KAAKS,QAAQ;AAC3G,aAAO,CAAA;IACT;AACA,UAAMC,WAAWH,OAAO9B,WAAYO,QAAQC;AAC5C,WAAOqB,MAAMK,OAAO,CAACC,MAAMA,EAAEC,YAAYC,IAAIJ,QAAAA,CAAAA;EAC/C;EAEOK,qBACLC,QACAC,SACAC,QACAC,SACmB;AACnB,UAAMC,kBAAkB,KAAK9C,SAAS0C,QAAQC,QAAQlC,MAAM;AAC5D,UAAMsC,kBAAkB,KAAK/C,SAAS4C,QAAQC,QAAQpC,MAAM;AAC5D,QAAKsC,oBAAoBtB,aAAYC,KAAKC,WAAYmB,oBAAoBrB,aAAYC,KAAKC,QAAQ;AACjGZ,MAAAA,KAAI,wCAAA,QAAA;;;;;;AACJ,aAAO+B,oBAAoBrB,aAAYC,KAAKC,QAAQgB,UAAUE;IAChE;AACA,WAAO;EACT;EAEOG,YAAY5C,WAA4C;AAC7D,UAAMiB,OAAOjB,WAAWiB,QAAQI,aAAYC,KAAKQ;AACjD,WAAOe,OAAOC,QAAQzB,aAAYC,IAAI,EAAEyB,KAAK,CAAC,CAACC,GAAGC,KAAAA,MAAWA,UAAUhC,IAAAA,EAAO,CAAA;EAChF;EAEOiC,gBAAgBC,IAAiBC,IAA0B;AAChE,WAAOD,IAAIlC,SAASmC,IAAInC;EAC1B;EAEQrB,SAASwB,OAAgCY,UAAuC;AACtF,QAAI,KAAKtD,WAAW0B,OAAO4B,QAAAA,GAAW;AACpC,aAAOX,aAAYC,KAAKC;IAC1B;AACA,UAAM8B,WAAWjC,MAAMkC,MAAMpC,IAAIc,QAAAA,GAAWhC,WAAWiB,QAAQI,aAAYC,KAAKQ;AAChF,QAAIV,MAAMmC,kBAAkB,MAAM;AAChC,YAAMC,WAAWpC,MAAMmC,eAAerC,IAAIc,QAAAA;AAC1C,UAAIwB,YAAY,MAAM;AACpB7C,QAAAA,KAAI,kCAAkC,OAAO;UAC3C8C,QAAQrC,MAAMsC,MAAMnD;UACpBoD,cAAc,KAAKf,YAAYY,SAASxD,SAAS;UACjDqD,UAAU,KAAKT,YAAYxB,MAAMkC,MAAMpC,IAAIc,QAAAA,GAAWhC,SAAAA;QACxD,IAAA;;;;;;AACA,eAAOwD,SAASxD,UAAUiB;MAC5B;IACF;AACA,WAAOoC;EACT;AACF;;;;;;;;;;AHrHO,IAAMO,oBAAN,MAAMA;;EACMC;EACAC;EACAC,eAAe,IAAIC,uBAAAA;EACnBC,eAAkC,CAAA;EAClCC,mBAAmB,IAAIC,YAAuCC,WAAUC,IAAI;EAC5EC,wBAAwB,IAAIC,YAAsBH,WAAUC,IAAI;EAEzEG;EACAC,wBAAmD,CAAA;EAElDC,wBAAwB,IAAIC,UAAAA;EAC5BC;EACAC;EACAC,wBAAwB,KAAKf,aAAae;EAC1CC,+BAA+B,KAAKhB,aAAagB;EAE1D,YAA6BC,WAAsB;SAAtBA,YAAAA;AAC3B,SAAKnB,WAAW,IAAIoB,mBAAmB,KAAKD,SAAS;AACrD,SAAKlB,SAAS,IAAIoB,iBAAiB,KAAKF,SAAS;AACjD,SAAKJ,sBAAsB,KAAKf,SAASe;AACzC,SAAKC,iBAAiB,KAAKf,OAAOe;EACpC;EAEA,IAAIM,UAAkC;AACpC,WAAO,KAAKtB,SAASsB;EACvB;EAEA,IAAIC,UAA8C;AAChD,WAAO,KAAKvB,SAASuB;EACvB;EAEA,IAAIC,uBAAoC;AACtC,WAAO,KAAKxB,SAASwB;EACvB;EAEA,IAAIC,QAA0C;AAC5C,WAAO,KAAKxB,OAAOwB;EACrB;EAEA,IAAIC,cAA4B;AAC9B,WAAO,KAAKtB,aAAauB,IAAI,CAACC,UAAUA,MAAMC,UAAU;EAC1D;EAEA,IAAIC,oBAAuC;AACzC,WAAO,KAAK1B;EACd;EAEA,IAAI2B,oBAA4C;AAC9C,WAAO,KAAKpB;EACd;EAEA,IAAIqB,cAA+D;AACjE,WAAO,KAAK9B,aAAa8B;EAC3B;EAEA,MAAMC,uBAAuBC,WAA+C;AAC1E,QAAI,KAAKtB,sBAAsBuB,KAAK,CAACC,MAAMA,EAAEF,cAAcA,SAAAA,GAAY;AACrE,YAAM,IAAIG,MAAM,qCAAA;IAClB;AAEA,UAAMC,WAAW,IAAIC,mBACnBL,WACA,YAAA;AACE,iBAAWL,cAAc,KAAKH,aAAa;AACzC,cAAMY,SAASE,SAASX,UAAAA;MAC1B;AAKAS,eAASG,6BAA6B;IACxC,GACA,YAAA;AACE,WAAK7B,wBAAwB,KAAKA,sBAAsB8B,OAAO,CAACN,MAAMA,MAAME,QAAAA;IAC9E,CAAA;AAEF,SAAK1B,sBAAsB+B,KAAKL,QAAAA;AAEhC,UAAMA,SAASM,KAAI;EACrB;EAEA,MAAMC,0BAA0BX,WAA+C;AAC7E,UAAMI,WAAW,KAAK1B,sBAAsBuB,KAAK,CAACC,MAAMA,EAAEF,cAAcA,SAAAA;AACxE,UAAMI,UAAUQ,MAAAA;EAClB;EAEAC,qBAAqBC,MAA2C;AAC9D,WAAO,KAAKtB,YAAYgB,OAAO,CAACb,eAAeoB,uBAAuBpB,UAAAA,EAAY,OAAA,MAAamB,IAAAA;EACjG;;;;;EAMA,MACME,QAAQrB,YAAwB,EAAEsB,YAAYC,iBAAgB,GAAsC;AACxG,QAAIvB,WAAWwB,IAAI;AACjB,UAAI,KAAK5C,sBAAsB6C,IAAIzB,WAAWwB,EAAE,GAAG;AACjD,eAAO;MACT;AACA,WAAK5C,sBAAsB8C,IAAI1B,WAAWwB,EAAE;IAC9C;AAEA,QAAI,CAACD,kBAAkB;AACrB,YAAMI,SAAS,MAAMC,iBAAiB5B,UAAAA;AACtC,UAAI2B,OAAOE,SAAS,QAAQ;AAC1BC,QAAAA,KAAIC,KAAK,uBAAuBJ,OAAOK,OAAOC,KAAK,IAAA,CAAA,IAAO,QAAA;;;;;;AAC1D,eAAO;MACT;IACF;AAEA,UAAMC,YAAYd,uBAAuBpB,UAAAA;AACzC,YAAQkC,UAAU,OAAA,GAAQ;MACxB,KAAK,sCAAsC;AACzC,YAAI,KAAKpD,oBAAoB;AAC3BgD,UAAAA,KAAIC,KAAK,2CAAA,QAAA;;;;;;AACT,iBAAO;QACT;AACA,YAAI,CAAC/B,WAAWmC,OAAOC,OAAO,KAAK9C,SAAS,GAAG;AAC7CwC,UAAAA,KAAIC,KAAK,qDAAA,QAAA;;;;;;AACT,iBAAO;QACT;AACA,YAAI,CAAC/B,WAAWqC,QAAQb,GAAGY,OAAO,KAAK9C,SAAS,GAAG;AACjDwC,UAAAA,KAAIC,KAAK,qDAAA,QAAA;;;;;;AACT,iBAAO;QACT;AACA,aAAKjD,qBAAqBkB;AAC1B;MACF;MAEA,KAAK,qCAAqC;AACxC,YAAI,CAACkC,UAAUI,SAASF,OAAO,KAAK9C,SAAS,GAAG;AAC9C;QACF;AAEA,YAAI,CAAC,KAAKR,oBAAoB;AAC5BgD,UAAAA,KAAIC,KAAK,+DAAA,QAAA;;;;;;AACT,iBAAO;QACT;AACA,YAAI,CAAC,KAAKQ,qBAAqBvC,WAAWmC,MAAM,GAAG;AACjDL,UAAAA,KAAIC,KAAK,yDAAyD/B,WAAWmC,MAAM,IAAE,QAAA;;;;;;AACrF,iBAAO;QACT;AAEA,cAAM,KAAKhE,SAASkD,QAAQrB,UAAAA;AAC5B,cAAM,KAAK3B,aAAagD,QAAQrB,UAAAA;AAChC;MACF;MAEA,KAAK,uCAAuC;AAC1C,YAAI,CAAC,KAAKlB,oBAAoB;AAC5BgD,UAAAA,KAAIC,KAAK,+DAAA,QAAA;;;;;;AACT,iBAAO;QACT;AAEA,cAAM,KAAK5D,SAASkD,QAAQrB,UAAAA;AAC5B;MACF;MAEA,KAAK,sCAAsC;AACzC,YAAI,CAAC,KAAKlB,oBAAoB;AAC5BgD,UAAAA,KAAIC,KAAK,gEAAA,QAAA;;;;;;AACT,iBAAO;QACT;AAGA,cAAM,KAAK3D,OAAOiD,QAAQrB,YAAYsB,UAAAA;AACtC;MACF;MACA,KAAK;MACL,KAAK,iDAAiD;AACpD,YAAI,CAAC,KAAKiB,qBAAqBvC,WAAWmC,MAAM,GAAG;AACjDL,UAAAA,KAAIC,KAAK,6EAA6E/B,WAAWmC,MAAM,IAAE,QAAA;;;;;;AACzG,iBAAO;QACT;AACA,cAAM,KAAK9D,aAAagD,QAAQrB,UAAAA;AAChC;MACF;IACF;AAEA,UAAMwC,WAA4B;MAAExC;MAAYsB;MAAYmB,SAAS;IAAM;AAC3E,SAAKlE,aAAauC,KAAK0B,QAAAA;AAGvB,QAAIxC,WAAWwB,IAAI;AACjB,WAAKhD,iBAAiBkE,IAAI1C,WAAWwB,IAAIgB,QAAAA;IAC3C;AAEA,eAAWnC,aAAa,KAAKtB,uBAAuB;AAClD,UAAIsB,UAAUO,4BAA4B;AACxC,cAAMP,UAAUM,SAASX,UAAAA;MAC3B;IACF;AAEA,UAAM,KAAKhB,sBAAsB2D,UAAU3C,UAAAA;AAC3C,WAAO;EACT;EAEO4C,cAAcC,WAAwC;AAC3D,WAAO,KAAK1E,SAAS2E,QAAQD,SAAAA;EAC/B;EAEOE,kCAAkCF,WAA+B;AACtE,WAAO,KAAKN,qBAAqBM,SAAAA;EACnC;EAEQN,qBAAqBS,KAAyB;AACpD,WACEA,IAAIZ,OAAO,KAAK9C,SAAS,KACzB,KAAKnB,SAAS2E,QAAQE,GAAAA,MAASC,aAAYC,KAAKC,SAChD,KAAKhF,SAAS2E,QAAQE,GAAAA,MAASC,aAAYC,KAAKE;EAEpD;AACF;;;;AAGA,IAAM1C,qBAAN,MAAMA;;;;EACI2C,OAAO,IAAIC,QAAAA,QAAAA;;;;;;;;;;EAQnB1C,6BAA6B;EAE7B,YACkBP,WACCkD,SACAC,UACjB;SAHgBnD,YAAAA;SACCkD,UAAAA;SACAC,WAAAA;EAChB;;;;EAKH,MAAM7C,SAASX,YAAuC;AACpD,UAAMyD,kBAAkB,KAAKJ,MAAM,YAAA;AACjC,YAAM,KAAKhD,UAAUqD,kBAAkB1D,UAAAA;IACzC,CAAA;EACF;EAEA,MAAMe,OAAsB;AAC1B,QAAI,KAAKsC,KAAKM,UAAU;AACtB,YAAM,IAAInD,MAAM,iCAAA;IAClB;AAEA,UAAM,KAAK+C,QAAO;EACpB;EAEA,MAAMtC,QAAuB;AAC3B,UAAM,KAAKoC,KAAKO,QAAO;AAEvB,UAAM,KAAKJ,SAAQ;EACrB;AACF;;;AKlTA,SAASK,eAAe;AACxB,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AAEpB,SAASC,cAAAA,mBAAkB;;AAepB,IAAMC,qBAAN,MAAMA;;;EAEKC,uBAAuB,IAAIC,YAA6CC,WAAUC,IAAI;EAEtFC,mBAAmB,IAAIC,QAAAA;EAEhCC;EAEP,YAA6BC,SAAkC;SAAlCA,UAAAA;EAAmC;EAEhE,MAAMC,kBAAkBC,YAAuC;AAC7DC,IAAAA,KAAI,4BAA4B;MAC9BC,aAAa,KAAKJ,QAAQI;MAC1BC,WAAW,KAAKL,QAAQK;MACxBH;IACF,GAAA;;;;;;AAGA,QAAII,kCAAkCJ,YAAY,KAAKF,QAAQI,aAAa,KAAKJ,QAAQK,SAAS,GAAG;AACnG,WAAKN,wBAAwB;QAAEG;MAAW;AAC1C,WAAKL,iBAAiBU,KAAI;IAC5B;AAEA,UAAMC,YAAYC,uBAAuBP,UAAAA;AAEzC,YAAQM,UAAU,OAAA,GAAQ;MACxB,KAAK,0CAA0C;AAG7C,aAAKf,qBAAqBiB,IAAIF,UAAUH,WAAW,KAAKZ,qBAAqBkB,IAAIH,UAAUH,SAAS,KAAK,CAAC,CAAA;AAE1GF,QAAAA,KAAI,gBAAgB;UAClBS,gBAAgB,KAAKZ,QAAQK;UAC7BA,WAAWG,UAAUH;UACrBQ,MAAM,KAAKpB,qBAAqBoB;QAClC,GAAA;;;;;;AACA,aAAKb,QAAQc,WAAQ;AACrB;MACF;MAEA,KAAK,uCAAuC;AAC1CC,QAAAA,WAAU,KAAKtB,qBAAqBuB,IAAId,WAAWe,QAAQC,EAAE,GAAG,qBAAA;;;;;;;;;AAEhE,YAAIV,aAAaN,WAAWe,QAAQC,GAAGC,OAAO,KAAKnB,QAAQK,SAAS,GAAG;AACrEF,UAAAA,KAAIiB,MAAM,oBAAoB;YAC5Bf,WAAWH,WAAWe,QAAQC;YAC9BG,SAASb,UAAUa;UACrB,GAAA;;;;;;QACF;AAEA,aAAK5B,qBAAqBiB,IAAIR,WAAWe,QAAQC,IAAIV,UAAUa,OAAO;AACtE,aAAKrB,QAAQc,WAAQ;AACrB;MACF;IACF;EACF;AACF;;;AC3EA,SAASQ,OAAAA,YAAW;;AAeb,IAAMC,sBAAN,MAAMA;;;EAEJC;EAEP,YAA6BC,SAAmC;SAAnCA,UAAAA;EAAoC;EAEjE,MAAMC,kBAAkBC,YAAuC;AAC7D,UAAMC,YAAYC,uBAAuBF,UAAAA;AACzC,YAAQC,UAAU,OAAA,GAAQ;MACxB,KAAK,yCAAyC;AAC5C,YACE,CAACD,WAAWG,OAAOC,OAAO,KAAKN,QAAQO,WAAW,KAClD,CAACL,WAAWM,QAAQC,GAAGH,OAAO,KAAKN,QAAQO,WAAW,GACtD;AACAG,UAAAA,KAAIC,KAAK,8BAA8B;YAAEC,kBAAkB,KAAKZ,QAAQO;YAAaL;UAAW,GAAA;;;;;;AAChG;QACF;AAGA,aAAKH,UAAUI,UAAUJ;AACzBW,QAAAA,KAAI,mBAAmB;UACrBH,aAAa,KAAKP,QAAQO;UAC1BR,SAAS,KAAKA;QAChB,GAAA;;;;;;AACA,aAAKC,QAAQa,WAAQ;AACrB;MACF;IACF;EACF;AACF;",
6
6
  "names": ["subtleCrypto", "IdentityDid", "PublicKey", "ComplexMap", "IDENTITY_DIDS_CACHE", "ComplexMap", "PublicKey", "hash", "createDidFromIdentityKey", "identityKey", "cachedValue", "get", "undefined", "digest", "subtleCrypto", "asUint8Array", "bytes", "Uint8Array", "slice", "IdentityDid", "byteLength", "identityDid", "encode", "set", "defaultSecretProvider", "Buffer", "from", "defaultSecretValidator", "invitation", "secret", "generateMnemonic", "mnemonicToSeedSync", "createKeyPair", "invariant", "generateSeedPhrase", "keyPairFromSeedPhrase", "seedPhrase", "seed", "generatePasscode", "length", "passcode", "i", "Math", "floor", "random", "stableStringify", "PublicKey", "Timeframe", "arrayToBuffer", "getCredentialProofPayload", "credential", "copy", "proof", "value", "Uint8Array", "chain", "undefined", "parentCredentialIds", "length", "id", "Buffer", "from", "canonicalStringify", "obj", "stableStringify", "replacer", "key", "toString", "startsWith", "original", "PublicKey", "isPublicKey", "toHex", "isBuffer", "arrayToBuffer", "data", "type", "Timeframe", "frames", "reduce", "seq", "truncateKey", "str", "substring", "getPresentationProofPayload", "credentials", "proof", "copy", "map", "credential", "removeEmptyParentCredentialIds", "value", "Uint8Array", "chain", "undefined", "Buffer", "from", "canonicalStringify", "parentCredentialIds", "length", "getCredentialAssertion", "credential", "subject", "assertion", "isValidAuthorizedDeviceCredential", "identityKey", "deviceKey", "id", "equals", "issuer", "checkCredentialType", "type", "credentialTypeFilter", "subtleCrypto", "invariant", "PublicKey", "verifySignature", "SIGNATURE_TYPE_ED25519", "verifyCredential", "credential", "parentCredentialIds", "length", "issuer", "equals", "proof", "signer", "chain", "kind", "errors", "result", "verifyChain", "verifyCredentialSignature", "type", "signData", "getCredentialProofPayload", "verifySignature", "value", "authority", "subject", "isValidAuthorizedDeviceCredential", "createCredential", "signer", "issuer", "subject", "assertion", "signingKey", "chain", "nonce", "parentCredentialIds", "invariant", "result", "verifyChain", "kind", "credential", "issuanceDate", "Date", "id", "proof", "type", "SIGNATURE_TYPE_ED25519", "creationDate", "value", "Uint8Array", "signedPayload", "getCredentialProofPayload", "sign", "PublicKey", "from", "subtleCrypto", "digest", "createCredentialMessage", "createCredentialSignerWithKey", "getIssuer", "createCredentialSignerWithChain", "AdmittedFeed", "SpaceMember", "Timeframe", "CredentialGenerator", "_signer", "_identityKey", "_deviceKey", "createSpaceGenesis", "spaceKey", "controlKey", "creatorProfile", "createCredential", "signer", "issuer", "subject", "assertion", "role", "SpaceMember", "Role", "ADMIN", "profile", "genesisFeedKey", "createFeedAdmission", "AdmittedFeed", "Designation", "CONTROL", "createMemberInvitation", "identityKey", "deviceKey", "dataKey", "EDITOR", "DATA", "createDeviceAuthorization", "createDeviceProfile", "feedKey", "designation", "createProfileCredential", "createEpochCredential", "number", "timeframe", "Timeframe", "credentials", "Promise", "all", "map", "credential", "createAdmissionCredentials", "membershipChainHeads", "invitationCredentialId", "parentCredentialIds", "createDelegatedSpaceInvitationCredential", "invitation", "invitationId", "authMethod", "swarmKey", "guestKey", "expiresOn", "multiUse", "createCancelDelegatedSpaceInvitationCredential", "credentialId", "signPresentation", "presentation", "signer", "signerKey", "chain", "nonce", "proof", "type", "SIGNATURE_TYPE_ED25519", "value", "Uint8Array", "creationDate", "Date", "signedPayload", "getPresentationProofPayload", "credentials", "sign", "proofs", "verifySignature", "verifyPresentation", "presentation", "errors", "credentialsVerifications", "Promise", "all", "credentials", "map", "credential", "verifyCredential", "verification", "kind", "push", "proofVerification", "proofs", "proof", "chainVerification", "verifyPresentationChain", "signatureVerification", "verifyPresentationSignature", "length", "issuer", "equals", "signer", "chain", "verifyChain", "subject", "id", "type", "SIGNATURE_TYPE_ED25519", "signData", "getPresentationProofPayload", "verifySignature", "value", "runInContextAsync", "synchronized", "Context", "PublicKey", "log", "SpaceMember", "Callback", "ComplexMap", "ComplexSet", "invariant", "PublicKey", "Callback", "ComplexMap", "FeedStateMachine", "_feeds", "ComplexMap", "PublicKey", "hash", "onFeedAdmitted", "Callback", "_spaceKey", "feeds", "process", "credential", "fromFeed", "assertion", "getCredentialAssertion", "invariant", "spaceKey", "equals", "info", "key", "subject", "id", "parent", "set", "callIfSet", "PublicKey", "Callback", "ComplexMap", "ComplexSet", "InvitationStateMachine", "_invitations", "ComplexMap", "PublicKey", "hash", "_redeemedInvitationCredentialIds", "ComplexSet", "_cancelledInvitationCredentialIds", "onDelegatedInvitation", "Callback", "onDelegatedInvitationRemoved", "invitations", "process", "credential", "credentialId", "id", "assertion", "getCredentialAssertion", "add", "existingInvitation", "get", "delete", "callIfSet", "invitation", "isExpired", "expiresOn", "getTime", "Date", "now", "wasUsed", "has", "multiUse", "wasCancelled", "set", "invitationCredentialId", "invariant", "PublicKey", "log", "SpaceMember", "ComplexMap", "invariant", "PublicKey", "log", "Callback", "ComplexMap", "ComplexSet", "CredentialGraph", "_vertexIdGenerator", "_root", "id", "parents", "children", "_sentinel", "_vertexByCredentialId", "hash", "_subjectToVertex", "_subjectToState", "onSubjectStateChanged", "_stateHandler", "getSubjectState", "subjectId", "get", "getState", "getLeafIds", "map", "v", "credential", "getGlobalStateScope", "state", "addVertex", "assertion", "newVertex", "set", "parentIds", "parentCredentialIds", "length", "push", "parentId", "parentVertex", "error", "_removeSentinelConnection", "_onVertexInserted", "vertex", "sentinelIdx", "indexOf", "splice", "vertexInSentinelIdx", "changedSubjects", "isUpdateAppliedOnTopOfThePreviousState", "subject", "isUpdateAllowed", "newSubjectState", "createState", "prevSubjectState", "hasStateChanged", "_recomputeState", "callIfSet", "pendingPaths", "Map", "paths", "_createRootPath", "lastPath", "path", "pop", "head", "_updatePathState", "convergedPaths", "_handleMergePoint", "mergeResult", "_mergePaths", "type", "_replayFailedPaths", "merged", "_forkTraversal", "p", "toChosenPath", "_setCurrentState", "replay", "stateOverrides", "forEach", "value", "key", "from", "chosenPath", "count", "overrides", "mapValues", "toLogString", "clearedPending", "filter", "l", "includes", "pendingList", "delete", "headCredential", "updatedSubject", "credentials", "add", "globalState", "forkChangedSubjects", "forkIssuers", "issuer", "newState", "replayChoice", "choices", "choice", "to", "fork", "forkPoint", "entries", "newStateMap", "newVertexMap", "subjectKey", "subjectVertex", "prevState", "_leastCommonAncestor", "uniqueForkPoints", "reduce", "acc", "it", "maxId", "maxState", "isPointInEveryPath", "every", "has", "_moveUpToForkPoint", "isForkPointInPath", "iss", "m", "forkPointId", "pathCount", "forkPoints", "fp", "result", "subjectToBranch", "modified", "cred", "modifiedSubject", "existingBranch", "_shouldOverrideCredential", "replayPaths", "Set", "addReplayPath", "bind", "branch", "otherPaths", "getConflictingPaths", "size", "values", "existing", "candidate", "candidateVertex", "currentVertex", "mergePointId", "candidateCredential", "currentCredential", "current", "winningCredential", "tryPickWinningUpdate", "issuerCount", "issuanceDate", "getTime", "Object", "fromEntries", "k", "vs", "MemberStateMachine", "_ownerKey", "_memberProfiles", "ComplexMap", "PublicKey", "hash", "_hashgraph", "CredentialGraph", "onMemberRoleChanged", "onSubjectStateChanged", "_spaceKey", "creator", "getSubjectState", "members", "getState", "membershipChainHeads", "getLeafIds", "getRole", "member", "_getRole", "getGlobalStateScope", "process", "credential", "assertion", "getCredentialAssertion", "invariant", "spaceKey", "equals", "issuer", "subject", "id", "profile", "set", "addVertex", "log", "warn", "Error", "createState", "memberKey", "key", "role", "get", "isUpdateAllowed", "scope", "SpaceMember", "Role", "OWNER", "isChangingOwnRole", "issuerRole", "ADMIN", "getConflictingPaths", "paths", "update", "REMOVED", "EDITOR", "memberId", "filter", "p", "forkIssuers", "has", "tryPickWinningUpdate", "scope1", "update1", "scope2", "update2", "path1IssuerRole", "path2IssuerRole", "toLogString", "Object", "entries", "find", "_", "value", "hasStateChanged", "s1", "s2", "realRole", "state", "stateOverrides", "override", "headId", "head", "roleOverride", "SpaceStateMachine", "_members", "_feeds", "_invitations", "InvitationStateMachine", "_credentials", "_credentialsById", "ComplexMap", "PublicKey", "hash", "_processedCredentials", "ComplexSet", "_genesisCredential", "_credentialProcessors", "onCredentialProcessed", "Callback", "onMemberRoleChanged", "onFeedAdmitted", "onDelegatedInvitation", "onDelegatedInvitationRemoved", "_spaceKey", "MemberStateMachine", "FeedStateMachine", "creator", "members", "membershipChainHeads", "feeds", "credentials", "map", "entry", "credential", "credentialEntries", "genesisCredential", "invitations", "addCredentialProcessor", "processor", "find", "p", "Error", "consumer", "CredentialConsumer", "_process", "_isReadyForLiveCredentials", "filter", "push", "open", "removeCredentialProcessor", "close", "getCredentialsOfType", "type", "getCredentialAssertion", "process", "sourceFeed", "skipVerification", "id", "has", "add", "result", "verifyCredential", "kind", "log", "warn", "errors", "join", "assertion", "issuer", "equals", "subject", "spaceKey", "_canInviteNewMembers", "newEntry", "revoked", "set", "callIfSet", "getMemberRole", "memberKey", "getRole", "hasMembershipManagementPermission", "key", "SpaceMember", "Role", "ADMIN", "OWNER", "_ctx", "Context", "_onOpen", "_onClose", "runInContextAsync", "processCredential", "disposed", "dispose", "Trigger", "invariant", "PublicKey", "log", "ComplexMap", "DeviceStateMachine", "authorizedDeviceKeys", "ComplexMap", "PublicKey", "hash", "deviceChainReady", "Trigger", "deviceCredentialChain", "_params", "processCredential", "credential", "log", "identityKey", "deviceKey", "isValidAuthorizedDeviceCredential", "wake", "assertion", "getCredentialAssertion", "set", "get", "localDeviceKey", "size", "onUpdate", "invariant", "has", "subject", "id", "equals", "trace", "profile", "log", "ProfileStateMachine", "profile", "_params", "processCredential", "credential", "assertion", "getCredentialAssertion", "issuer", "equals", "identityKey", "subject", "id", "log", "warn", "expectedIdentity", "onUpdate"]
7
7
  }