{"id":31847900,"url":"https://github.com/wireapp/generic-message-proto","last_synced_at":"2025-10-12T09:58:22.263Z","repository":{"id":5634605,"uuid":"53574487","full_name":"wireapp/generic-message-proto","owner":"wireapp","description":"Protocol definition for generic messages.","archived":false,"fork":false,"pushed_at":"2025-09-26T08:44:47.000Z","size":328,"stargazers_count":35,"open_issues_count":3,"forks_count":23,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-09-26T10:28:53.848Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@wireapp/protocol-messaging","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wireapp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-03-10T10:04:24.000Z","updated_at":"2025-07-23T14:49:08.000Z","dependencies_parsed_at":"2024-05-16T18:30:43.142Z","dependency_job_id":"8f090522-4766-4ad7-accb-58a96c9b7b67","html_url":"https://github.com/wireapp/generic-message-proto","commit_stats":{"total_commits":123,"total_committers":30,"mean_commits":4.1,"dds":0.7967479674796748,"last_synced_commit":"ff36abddb9d668709e0c793ddc8d034ebfafd8f9"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"purl":"pkg:github/wireapp/generic-message-proto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fgeneric-message-proto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fgeneric-message-proto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fgeneric-message-proto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fgeneric-message-proto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wireapp","download_url":"https://codeload.github.com/wireapp/generic-message-proto/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wireapp%2Fgeneric-message-proto/sbom","scorecard":{"id":1238181,"data":{"date":"2025-07-21","repo":{"name":"github.com/wireapp/generic-message-proto","commit":"bc03f619b3ed2ed2d8472b360624928313fe598f"},"scorecard":{"version":"v5.2.1-24-gc29a04d4","commit":"c29a04d46d1570393e94662bc34e9906398e1bfa"},"score":4.3,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#maintained"}},{"name":"Code-Review","score":3,"reason":"Found 8/26 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/wireapp/generic-message-proto/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/wireapp/generic-message-proto/ci.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#security-policy"}},{"name":"SAST","score":3,"reason":"SAST tool is not run on all commits -- score normalized to 3","details":["Warn: 5 commits out of 13 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c29a04d46d1570393e94662bc34e9906398e1bfa/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-09-26T10:30:47.880Z","repository_id":5634605,"created_at":"2025-09-26T10:30:47.881Z","updated_at":"2025-09-26T10:30:47.881Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002538,"owners_count":26083401,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-12T09:58:21.060Z","updated_at":"2025-10-12T09:58:22.252Z","avatar_url":"https://github.com/wireapp.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wire\n\nThis repository is part of the source code of Wire. You can find more information at [wire.com](https://wire.com) or by contacting opensource@wire.com.\n\nYou can find the published source code at [github.com/wireapp/wire](https://github.com/wireapp/wire).\n\nFor licensing information, see the attached LICENSE file and the list of third-party licenses at [wire.com/legal/licenses/](https://wire.com/legal/licenses/).\n\n# GenericMessage protocol\nProtocol definition for generic messages.\n\n`GenericMessage` is supposed to be used in client messages ('client-message-add' event) and in OTR encrypted messages. Once E2EE is released client messages will no longer be used.\n\n`GenericMessage` contains message id and specific message content (`oneOf`)\n\n## Message Id\n`MessageId` field is client generated identifier of a message this `GenericMessage` relates to, it should be used by all clients to correlate message updates. This is **not** unique event id, there may (and will) be several `GenericMessage` events with the same `messageId`, each `GenericMessage` provides part of final message or some update to it.\n\nEach ImageAsset version/tag is sent in separate request which means there are several `GenericMessage` events for each asset, all of them will use the same `messageId`, this actually replaces `correlationId` from regular asset events. It will be the same for different updates, for example *like* events, they will all contain `messageId` of references message.\n\n### Id collisions\nClients need to take case of message id collisions. It is possible, that some malicious client will generate events with the same id in order to override other messages. Every time `GenericMessage` is received, client need to check if it already has a message with the same id and make sure that this is a valid update. If received event is not valid update (for example sender doesn't match to original message author in text messages), then clients is allowed to drop the message or use different id for it. Using different id is preferred to handle unintended collisions or to expose buggy sender behaviour.\n\n## Message Content\nActual message content is included as `oneof` field in `GenericMessage`, this way we can later add more message types in backward compatible manner.\n\n### Availability\nA user sends a generic message of type `Availability` if he wants to change his personal availability. The availability can be of four types: `None`, `Available`, `Busy`, and `Away`.\n\n### Text\nRegular text message content, optionally including a list of mentioned users.\n\n#### Mention\nDescribes user mentioned in text message. Contains `user_id`, `start` and `end` offsets of the mention string in UTF16 characters. The offset is used to highlight mention text inside the message. `user_id` is optional because to keep it backwards compatible when mentioning more than one user e.g. @everyone or @some_team. \n\n### Knock\n\n### LastRead\nInternal message, sent on self conversation to notify other clients (belonging to the same user) about messages being read in some conversation.\n\n### Cleared\nInternal message, sent on self conversation to notify other clients about conversation being cleared.\n\n### MessageHide\nInternal message, sent on self conversation to notify other clients about message being locally deleted.\n\n### MessageDelete\nMessage sent to recall previously sent message, can be only sent by original author of deleted message.\n\n### MessageEdit\nIf the content of a previously sent message should be edited, a generic message of type `MessageEdit` has to be sent.\nIt should reference the new content (for now only type `Text` can be edited) as well as the nonce of the message it is replacing. If an edit message is received which is referencing a non existent nonce it should be discarded.\n\n### Confirmation\nIf the reception of a previously sent message should be confirmed, a generic message of type `Confirmation` has to be sent. It should reference the message to be confirmed. Currently the confirmation comes in two flavours: `Read` and `Delivered`.\n\n### Location\nLocation sharing message, contains GPS coordinates (latitude and longitude) and optional location name string.\n\n### Reaction\nExpresses a reaction to a previously received message. The reaction itself can be any string but should be an emoji. If there are multiple reactions from one user to the same message, only the most recent one should be kept. In order to remove/clear a previous reaction, the empty string should be sent.\n\n### ImageAsset\nContains metadata for single image asset version, most fields correspond to metadata sent on regular assets endpoint.\nThere are three special fields:\n\n- `otr_key` - optional symmetric encryption key. If asset message includes this key, then asset stored on backend is encrypted, and clients can use this key to decrypt original image data.\n- `sha256` - hash of encrypted asset ciphertext. Should be provided for encrypted messages, clients should check it before trying to decrypt an asset.\n\nAsset encryption should follow similar procedure as symmetric encryption in native push notifications.\nEncryption with standard AES256 in CBC mode with PKCS#5/7 padding and the initialization vector (IV) prepended to the ciphertext.\nSHA256 is computed from cyphertext, receiving client validates it before decrypting an asset.\n\n### Asset\nMetadata for generic file uploads. Intended to supersede ImageAsset at a later point. For encryption and related fields, see ImageAsset.\n\nThis message can be received in up to 3 parts which then can be merged together to build a complete asset record.\n\n- Upload is starting: the field `original` is set with basic info about the file being uploaded.\n- Preview has been uploaded: the field `preview` is set with basic info about the preview as well as the encryption fields. This step is optional.\n- One of two messages arrive next:\n  + File upload is cancelled or has failed, in which case the `status.not_uploaded` field is set with the appropriate value.\n  + File upload has completed successfully. The `status.uploaded` field is set with encryption info provided.\n\n### External\nThis message content is used if original message results in large payload, that would not be accepted by backend.\nRegular messages are encrypted multiple times (per recipient) and in case of multiple participants even quite small\nmessage can generate huge payload.\nIn that case we want to encrypt original message with symmetric encryption and only send a key to all participants.\n\nClients use fallowing procedure when sending a message:\n\n- generate original `GenericMessage` (`OM`)\n- estimate payload size - client could run regular encryption step and check the size of encrypted data, or could estimate the size based on participants count (make sure to recheck if new participant is added after `ClientMismatch` error)\n- if payload is smaller than 256KB then `OM` can be sent directly\n- if payload is too big:\n  - encrypt `OM` using symmetric encryption (the same way as for assets)\n  - create `External` message with AES key and sha of encrypted data\n  - send message with `External` content and encrypted `OM` attached (`data` field in json)\n\n## Forward compatibility\nMessages sent through OTR can be decrypted only once, so it's important not to loose any info, even when receiving a message that can not be fully decoded (when using older app version). It would be advisable to save original `GenericMessage` data and decode it again after app update. This should be done at least when decoded message seems to have no `content`, this will happen when new content type is added, in that case old app will think that the message is empty.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwireapp%2Fgeneric-message-proto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwireapp%2Fgeneric-message-proto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwireapp%2Fgeneric-message-proto/lists"}