mirror of
https://github.com/vacp2p/rfc.vac.dev.git
synced 2026-08-31 04:01:10 +00:00
186 lines
143 KiB
HTML
186 lines
143 KiB
HTML
<!doctype html>
|
||
<html lang="en" dir="ltr" class="docs-wrapper docs-doc-page docs-version-current plugin-docs plugin-id-status docs-doc-id-71/push-notification-server">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="generator" content="Docusaurus v2.4.1">
|
||
<title data-rh="true">71/STATUS-PUSH-NOTIFICATION-SERVER | Vac Research</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://vac.dev/status/71/push-notification-server"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="image" content="https://vac.dev/_og/56b88e740d69863c377148f55cfc46ce99b87374.png"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-status-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-status-current"><meta data-rh="true" property="og:title" content="71/STATUS-PUSH-NOTIFICATION-SERVER | Vac Research"><meta data-rh="true" name="description" content="A set of methods to allow Status clients to use push notification services in mobile environments."><meta data-rh="true" property="og:description" content="A set of methods to allow Status clients to use push notification services in mobile environments."><link data-rh="true" rel="icon" href="/theme/image/favicon.ico"><link data-rh="true" rel="canonical" href="https://vac.dev/status/71/push-notification-server"><link data-rh="true" rel="alternate" href="https://vac.dev/status/71/push-notification-server" hreflang="en"><link data-rh="true" rel="alternate" href="https://vac.dev/status/71/push-notification-server" hreflang="x-default"><link rel="alternate icon" type="image/png" href="/theme/image/favicon.png">
|
||
<link rel="icon" type="image/svg+xml" href="/theme/image/favicon.svg">
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css" integrity="sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM" crossorigin="anonymous"><link rel="stylesheet" href="/assets/css/styles.7f69a75a.css">
|
||
<link rel="preload" href="/assets/js/runtime~main.db01e95f.js" as="script">
|
||
<link rel="preload" href="/assets/js/main.7bd63d25.js" as="script">
|
||
<meta property="og:image" content="https://vac.dev/_og/56b88e740d69863c377148f55cfc46ce99b87374.png"><meta name="twitter:image" content="https://vac.dev/_og/56b88e740d69863c377148f55cfc46ce99b87374.png"></head>
|
||
<body class="navigation-with-keyboard">
|
||
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}return t}()||function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"dark")}()</script><div id="__docusaurus">
|
||
<style data-emotion="css-global 3rtehh">.lsd-button{width:auto;cursor:pointer;padding:6px 24px;}.lsd-button--disabled{cursor:default;opacity:0.34;}.lsd-button--large{padding:10px 40px;}.lsd-button--medium{padding:6px 24px;}.lsd-button--small{padding:6px 12px;}.lsd-button:hover:not(.lsd-button--disabled) .lsd-button__text{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-button--with-icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-button__icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;}.lsd-button--large.lsd-button--with-icon{padding:10px 0px 10px 18px;}.lsd-button--large.lsd-button--with-icon .lsd-button__icon{width:42px;}.lsd-button--medium.lsd-button--with-icon{padding:6px 0px 6px 14px;}.lsd-button--medium.lsd-button--with-icon .lsd-button__icon{width:38px;}.lsd-button--small.lsd-button--with-icon{padding:6px 0px 6px 12px;}.lsd-button--small.lsd-button--with-icon .lsd-button__icon{width:34px;}.lsd-button--outlined{background:none;border:1px solid rgb(var(--lsd-border-primary));}.lsd-button--outlined .lsd-button__text{color:rgb(var(--lsd-text-primary));}.lsd-button--filled{background:rgb(var(--lsd-surface-secondary));border:1px solid rgb(var(--lsd-border-primary));}.lsd-button--filled .lsd-button__text{color:rgb(var(--lsd-text-secondary));}</style><style data-emotion="css-global 10bahxd">.lsd-icon-button{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;cursor:pointer;background:none;padding:0;border:1px solid rgb(var(--lsd-border-primary));}.lsd-icon-button--filled{background-color:rgb(var(--lsd-icon-primary));}.lsd-icon-button--filled svg{--lsd-icon-primary:var(--lsd-icon-secondary);}.lsd-icon-button--disabled{opacity:0.34;cursor:default;}.lsd-icon-button--large{width:40px;height:40px;}.lsd-icon-button--medium{width:32px;height:32px;}.lsd-icon-button--small{width:28px;height:28px;}</style><style data-emotion="css-global icqph9">.lsd-icon-button-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}.lsd-icon-button-group--outlined .lsd-icon-button:not(:last-child){border-right:none;}</style><style data-emotion="css-global 1f43ub2">body *{font-family:var(--lsd-typography-generic-font-family);}.lsd-typography{color:rgb(var(--lsd-text-primary));}.lsd-typography--sans-serif,.lsd-typography--sans-serif *{font-family:sans-serif;}.lsd-typography--serif,.lsd-typography--serif *{font-family:serif;}.lsd-typography--monospace,.lsd-typography--monospace *{font-family:monospace;}.lsd-typography--display1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display1-fontWeight);font-size:var(--lsd-display1-fontSize);line-height:var(--lsd-display1-lineHeight);}.lsd-typography--display2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display2-fontWeight);font-size:var(--lsd-display2-fontSize);line-height:var(--lsd-display2-lineHeight);}.lsd-typography--display3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display3-fontWeight);font-size:var(--lsd-display3-fontSize);line-height:var(--lsd-display3-lineHeight);}.lsd-typography--display4{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display4-fontWeight);font-size:var(--lsd-display4-fontSize);line-height:var(--lsd-display4-lineHeight);}h1,.lsd-typography--h1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h1-fontWeight);font-size:var(--lsd-h1-fontSize);line-height:var(--lsd-h1-lineHeight);}h2,.lsd-typography--h2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h2-fontWeight);font-size:var(--lsd-h2-fontSize);line-height:var(--lsd-h2-lineHeight);}h3,.lsd-typography--h3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h3-fontWeight);font-size:var(--lsd-h3-fontSize);line-height:var(--lsd-h3-lineHeight);}h4,.lsd-typography--h4{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h4-fontWeight);font-size:var(--lsd-h4-fontSize);line-height:var(--lsd-h4-lineHeight);}h5,.lsd-typography--h5{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h5-fontWeight);font-size:var(--lsd-h5-fontSize);line-height:var(--lsd-h5-lineHeight);}h6,.lsd-typography--h6{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h6-fontWeight);font-size:var(--lsd-h6-fontSize);line-height:var(--lsd-h6-lineHeight);}.lsd-typography--subtitle1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle1-fontWeight);font-size:var(--lsd-subtitle1-fontSize);line-height:var(--lsd-subtitle1-lineHeight);}.lsd-typography--subtitle2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle2-fontWeight);font-size:var(--lsd-subtitle2-fontSize);line-height:var(--lsd-subtitle2-lineHeight);}.lsd-typography--subtitle3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle3-fontWeight);font-size:var(--lsd-subtitle3-fontSize);line-height:var(--lsd-subtitle3-lineHeight);}.lsd-typography--subtitle4{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle4-fontWeight);font-size:var(--lsd-subtitle4-fontSize);line-height:var(--lsd-subtitle4-lineHeight);}body,.lsd-typography--body1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-body1-fontWeight);font-size:var(--lsd-body1-fontSize);line-height:var(--lsd-body1-lineHeight);}.lsd-typography--body2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-body2-fontWeight);font-size:var(--lsd-body2-fontSize);line-height:var(--lsd-body2-lineHeight);}.lsd-typography--body3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-body3-fontWeight);font-size:var(--lsd-body3-fontSize);line-height:var(--lsd-body3-lineHeight);}label,.lsd-typography--label1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-label1-fontWeight);font-size:var(--lsd-label1-fontSize);line-height:var(--lsd-label1-lineHeight);}.lsd-typography--label2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-label2-fontWeight);font-size:var(--lsd-label2-fontSize);line-height:var(--lsd-label2-lineHeight);}.lsd-typography--primary{color:rgb(var(--lsd-text-primary));}.lsd-typography--secondary{color:rgb(var(--lsd-text-secondary));}input{color:rgb(var(--lsd-text-primary));font-size:var(--lsd-body1-fontSize);font-weight:var(--lsd-body1-fontWeight);}h1,h2,h3,h4,h5,h6,p,span{margin:0;}</style><style data-emotion="css-global 1yxb6i5">.lsd-icon--primary.lsd-icon--filled,.lsd-icon--primary.lsd-icon--filled *{fill:rgb(var(--lsd-icon-primary));}.lsd-icon--primary $.lsd-icon--stroked,.lsd-icon--primary $.lsd-icon--stroked *{fill:rgb(var(--lsd-icon-primary));}.lsd-icon--secondary.lsd-icon--filled,.lsd-icon--secondary.lsd-icon--filled *{fill:rgb(var(--lsd-icon-secondary));}.lsd-icon--secondary $.lsd-icon--stroked,.lsd-icon--secondary $.lsd-icon--stroked *{fill:rgb(var(--lsd-icon-secondary));}</style><style data-emotion="css-global 1hozxbf">.lsd-tab-item{background:rgb(var(--lsd-surface-primary));border:1px solid transparent;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;}.lsd-tab-item:hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-tab-item:not(lsd-tab-item--selected){border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-tab-item--text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.lsd-tab-item--icon{margin-left:14px;}.lsd-tab-item--selected{border:1px solid rgb(var(--lsd-border-primary));}.lsd-tab-item--selected:hover{-webkit-text-decoration:none;text-decoration:none;}.lsd-tab-item--with-icon{-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-tab-item--disabled{cursor:default;opacity:0.34;}.lsd-tab-item--disabled:hover{-webkit-text-decoration:none;text-decoration:none;}.lsd-tab-item--small{padding:6px 12px;}.lsd-tab-item--small .lsd-tab-item--icon{margin-left:10px;}.lsd-tab-item--medium{padding:6px 14px;}.lsd-tab-item--medium .lsd-tab-item--icon{margin-left:12px;}.lsd-tab-item--large{padding:10px 18px;}.lsd-tab-item--large .lsd-tab-item--icon{margin-left:14px;}</style><style data-emotion="css-global 1a24j7d">.lsd-tabs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;overflow:auto;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:100%;border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-tabs>*{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-tabs .lsd-tab-item{border-bottom:none;}.lsd-tabs--full-width{width:100%;-webkit-box-pack:stretch;-ms-flex-pack:stretch;-webkit-justify-content:stretch;justify-content:stretch;}.lsd-tabs--full-width>*{width:100%;-webkit-flex:1 0;-ms-flex:1 0;flex:1 0;}.lsd-tabs{-ms-overflow-style:none;scrollbar-width:none;}.lsd-tabs::-webkit-scrollbar{display:none;}.lsd-tabs__left-scroll-control{left:0;}.lsd-tabs__right-scroll-control{right:0;}.lsd-tabs__right-scroll-control,.lsd-tabs__left-scroll-control{top:0;-webkit-flex:0 1;-ms-flex:0 1;flex:0 1;position:-webkit-sticky;position:sticky;}</style><style data-emotion="css-global 1v7gjjb">.lsd-dropdown-menu{position:absolute;top:0;left:0;opacity:0;visibility:hidden;margin:0;padding:0;box-sizing:border-box;background:rgb(var(--lsd-surface-primary));overflow:auto;border:1px solid rgb(var(--lsd-border-primary));border-top:0;}.lsd-dropdown-menu>div{border:0;}.lsd-dropdown-menu>div:not(:last-child){border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown-menu--open{opacity:1;visibility:visible;}.lsd-dropdown-menu--large{max-height:220px;}.lsd-dropdown-menu--medium{max-height:176px;}.lsd-dropdown-menu--small{max-height:154px;}</style><style data-emotion="css-global hyd3xb">.lsd-dropdown:not(.lsd-dropdown--disabled):not(
|
||
.lsd-dropdown--error
|
||
) .lsd-dropdown__trigger:hover .lsd-dropdown__option-label,.lsd-dropdown:not(.lsd-dropdown--disabled):not(
|
||
.lsd-dropdown--error
|
||
) .lsd-dropdown__trigger:focus .lsd-dropdown__option-label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-dropdown__label{display:block;}.lsd-dropdown__button-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-dropdown__trigger{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;border:none;cursor:pointer;background:none;}.lsd-dropdown__trigger:focus{outline:none;}.lsd-dropdown__option-label{cursor:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.lsd-dropdown__icons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;gap:8px;}.lsd-dropdown__icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-dropdown__supporting-text{margin:6px 14px;}.lsd-dropdown--error .lsd-dropdown__option-label{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-dropdown--disabled{opacity:0.34;cursor:initial;}.lsd-dropdown--large{width:208px;}.lsd-dropdown--large.lsd-dropdown--error{width:230px;}.lsd-dropdown--large .lsd-dropdown__label{margin:0 0 6px 18px;}.lsd-dropdown--large .lsd-dropdown__button-container{height:40px;}.lsd-dropdown--large .lsd-dropdown__trigger{padding:10px 0px 10px 18px;}.lsd-dropdown--large .lsd-dropdown__icons{padding:0px 14px;}.lsd-dropdown--medium{width:188px;}.lsd-dropdown--medium.lsd-dropdown--error{width:210px;}.lsd-dropdown--medium .lsd-dropdown__label{margin:0 0 6px 14px;}.lsd-dropdown--medium .lsd-dropdown__button-container{height:32px;}.lsd-dropdown--medium .lsd-dropdown__trigger{padding:6px 0px 6px 14px;}.lsd-dropdown--medium .lsd-dropdown__icons{padding:0px 12px;}.lsd-dropdown--small{width:164px;}.lsd-dropdown--small.lsd-dropdown--error{width:186px;}.lsd-dropdown--small .lsd-dropdown__label{margin:0 0 6px 12px;}.lsd-dropdown--small .lsd-dropdown__button-container{height:28px;}.lsd-dropdown--small .lsd-dropdown__trigger{padding:6px 0px 6px 12px;}.lsd-dropdown--small .lsd-dropdown__icons{padding:0px 10px;}.lsd-dropdown--outlined .lsd-dropdown__button-container{border:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown--underlined .lsd-dropdown__button-container{border:1px solid transparent;border-bottom:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global w2g5fy">.lsd-dropdown-item{width:100%;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled){cursor:pointer;}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):hover,.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):focus{outline:none;}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):hover .lsd-dropdown-item__label,.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):focus .lsd-dropdown-item__label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-dropdown-item__label{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.lsd-dropdown-item--disabled{opacity:0.34;}.lsd-dropdown-item__icon{margin-right:18px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-dropdown-item--small{padding:5px 9px;height:28px;}.lsd-dropdown-item--medium{padding:5px 11px;height:32px;}.lsd-dropdown-item--large{padding:5px 13px;height:40px;}</style><style data-emotion="css-global ww9kgc">.lsd-breadcrumb__list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;list-style-type:none;margin:0;padding:0;}.lsd-breadcrumb--disabled .lsd-breadcrumb__list{opacity:0.34;cursor:initial;pointer-events:none;}.lsd-breadcrumb__dropdown-menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:auto;border:1px solid rgb(var(--lsd-border-primary));margin-top:10px;position:absolute;width:auto!important;}.lsd-breadcrumb__dropdown-menu>li{cursor:pointer;}.lsd-breadcrumb__dropdown-menu>li:not(:last-child){border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-breadcrumb__dropdown-menu>li:hover,.lsd-breadcrumb__dropdown-menu>li:focus{-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgb(var(--lsd-border-primary));}.lsd-breadcrumb__dropdown-menu li>a{width:164px;padding:5px 11px;}</style><style data-emotion="css-global 4gvini">.lsd-breadcrumb-item{list-style-type:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-breadcrumb__list>li:not(:last-child)::after{display:inline-block;margin-inline:12px;content:'/';}.lsd-breadcrumb-item__link{-webkit-text-decoration:none;text-decoration:none;cursor:pointer;}.lsd-breadcrumb-item--outlined{padding:3px 11px;border:1px solid rgb(var(--lsd-border-primary));}.lsd-breadcrumb:not(.lsd-breadcrumb--disabled) .lsd-breadcrumb-item__link:hover,.lsd-breadcrumb:not(.lsd-breadcrumb--disabled) .lsd-breadcrumb-item__link:focus{-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 1cwg3oc">.lsd-card{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-card>.lsd-card-header{margin-bottom:-1px;}</style><style data-emotion="css-global v7d76i">.lsd-card-header{box-sizing:border-box;padding:10px 18px;text-align:center;border:1px solid rgb(var(--lsd-border-primary));}.lsd-card-header__title{overflow:hidden;word-break:break-all;}.lsd-card-header--large{padding:10px 18px;}.lsd-card-header--medium{padding:6px 14px;}.lsd-card-header--small{padding:6px 12px;}</style><style data-emotion="css-global 1txgafh">.lsd-card-body{box-sizing:border-box;padding:14px 22px;border:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global kzy52c">.lsd-tag{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;border:1px solid rgb(var(--lsd-icon-primary));}.lsd-tag:hover,.lsd-tag:focus{-webkit-text-decoration:underline;text-decoration:underline;cursor:pointer;}.lsd-badge--large{padding:3px 11px;gap:12px;height:28px;}.lsd-badge--small{padding:3px 7px;gap:8px;height:24px;}.lsd-tag--filled{background-color:rgb(var(--lsd-icon-primary));}.lsd-tag--filled .lsd-tag__label{color:rgb(var(--lsd-text-secondary));}.lsd-tag--filled svg{--lsd-icon-primary:var(--lsd-icon-secondary);}.lsd-tag--outlined{color:rgb(var(--lsd-text-primary));}.lsd-tag--disabled{opacity:0.3;cursor:initial;pointer-events:none;}</style><style data-emotion="css-global 4wy0ub">.lsd-text-field{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-text-field__input-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-text-field--disabled{opacity:0.34;}.lsd-text-field__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;width:100%;}.lsd-text-field__input:hover{outline:none;}.lsd-text-field__input::-webkit-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field__input::-moz-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field__input:-ms-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field__input::placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field--error .lsd-text-field__input{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-text-field__supporting-text{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-text-field--large{width:208px;}.lsd-text-field--large>*{padding:10px 14px 10px 18px;}.lsd-text-field--medium{width:188px;}.lsd-text-field--medium>*{padding:6px 12px 6px 14px;}.lsd-text-field--small{width:164px;}.lsd-text-field--small>*{padding:6px 10px 6px 12px;}.lsd-text-field__label{padding-top:0;padding-bottom:6px;}.lsd-text-field__supporting-text{padding-bottom:0;padding-top:6px;}.lsd-text-field--outlined .lsd-text-field__input-container{border:1px solid rgb(var(--lsd-border-primary));}.lsd-text-field--underlined .lsd-text-field__input-container{border:1px solid transparent;border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-text-field__clear-button{padding:0;width:auto;height:auto;margin:0;border:0;}</style><style data-emotion="css-global uhig7c">.lsd-checkbox{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-checkbox__input{opacity:0;position:absolute;left:0;top:0;padding:0;margin:0;width:100%;height:100%;}.lsd-checkbox:not(.lsd-checkbox--disabled):hover,.lsd-checkbox:not(.lsd-checkbox--disabled).lsd-checkbox--focused{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-checkbox:not(.lsd-checkbox--disabled) .lsd-checkbox__input{cursor:pointer;}.lsd-checkbox--disabled{opacity:0.34;}.lsd-checkbox__label{margin-left:18px;}.lsd-checkbox--large .lsd-checkbox__label{margin-left:18px;}.lsd-checkbox--medium .lsd-checkbox__label{margin-left:14px;}.lsd-checkbox--small .lsd-checkbox__label{margin-left:12px;}</style><style data-emotion="css-global txommo">.lsd-autocomplete{box-sizing:border-box;}.lsd-autocomplete__label{display:block;}.lsd-autocomplete__input-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-autocomplete--disabled{opacity:0.34;}.lsd-autocomplete__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;width:100%;}.lsd-autocomplete__input:hover{outline:none;}.lsd-autocomplete__input::-webkit-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__input::-moz-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__input:-ms-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__input::placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__icon{cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-autocomplete--error{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-autocomplete--large{width:208px;}.lsd-autocomplete--large .lsd-autocomplete__label{margin:0 0 6px 18px;}.lsd-autocomplete--large .lsd-autocomplete__input-container{height:40px;}.lsd-autocomplete--large .lsd-autocomplete__input{padding:9px 17px;}.lsd-autocomplete--large .lsd-autocomplete__icon{padding:12px 13px;}.lsd-autocomplete--medium{width:188px;}.lsd-autocomplete--medium .lsd-autocomplete__label{margin:0 0 6px 14px;}.lsd-autocomplete--medium .lsd-autocomplete__input-container{height:32px;}.lsd-autocomplete--medium .lsd-autocomplete__input{padding:5px 13px;}.lsd-autocomplete--medium .lsd-autocomplete__icon{padding:8px 11px;}.lsd-autocomplete--small{width:164px;}.lsd-autocomplete--small .lsd-autocomplete__label{margin:0 0 6px 12px;}.lsd-autocomplete--small .lsd-autocomplete__input-container{height:28px;}.lsd-autocomplete--small .lsd-autocomplete__input{padding:5px 11px;}.lsd-autocomplete--small .lsd-autocomplete__icon{padding:6px 9px;}.lsd-autocomplete--outlined .lsd-autocomplete__input-container{border:1px solid rgb(var(--lsd-border-primary));}.lsd-autocomplete--underlined .lsd-autocomplete__input-container{border:1px solid transparent;border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-autocomplete__dropdown-item-placeholder{opacity:0.5;white-space:pre;}</style><style data-emotion="css-global quxxm6">.lsd-quote{color:rgb(var(--lsd-text-primary));white-space:pre-wrap;}.lsd-quote--indented-inline{border-left:1px solid rgb(var(--lsd-border-primary));padding:4px 8px 4px 28px;}.lsd-quote--parentheses{padding:0px;text-align:center;}.lsd-quote--parentheses::before{content:'***';}.lsd-quote--parentheses::after{content:'***';}</style><style data-emotion="css-global a49t4h">.lsd-collapse{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-collapse--open .lsd-collapse__content{border-top:1px solid transparent;}.lsd-collapse__content{border:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 12ppw0q">.lsd-collapse-header{box-sizing:border-box;}.lsd-collapse-header:not(.lsd-collapse-header--disabled) .lsd-collapse-header__trigger:hover .lsd-collapse-header__label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-collapse-header__trigger{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;cursor:pointer;background:none;border:1px solid rgb(var(--lsd-border-primary));}.lsd-collapse-header__trigger:focus{outline:none;}.lsd-collapse-header__label{cursor:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:auto;}.lsd-collapse-header__icons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;}.lsd-collapse-header__icon{margin-right:8px;}.lsd-collapse-header--disabled .lsd-collapse-header__trigger{opacity:0.34;cursor:initial;}.lsd-collapse-header--large .lsd-collapse-header__trigger{width:299px;height:40px;padding:9px 17px;}.lsd-collapse-header--medium .lsd-collapse-header__trigger{width:270px;height:32px;padding:5px 13px;}.lsd-collapse-header--small .lsd-collapse-header__trigger{width:235px;height:28px;padding:5px 11px;}</style><style data-emotion="css-global dixc0i">.lsd-checkbox-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:6px;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-checkbox-group__label{margin-bottom:6px;}</style><style data-emotion="css-global q2n2hz">.lsd-badge{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;border:1px solid rgb(var(--lsd-icon-primary));border-radius:20px;}.lsd-badge:hover,.lsd-badge:focus{-webkit-text-decoration:underline;text-decoration:underline;cursor:pointer;}.lsd-badge--large{padding:3px 11px;gap:12px;height:28px;}.lsd-badge--small{padding:3px 7px;gap:8px;height:24px;}.lsd-badge--filled{background-color:rgb(var(--lsd-icon-primary));}.lsd-badge--filled .lsd-badge__label{color:rgb(var(--lsd-text-secondary));}.lsd-badge--filled svg{--lsd-icon-primary:var(--lsd-icon-secondary);}.lsd-badge--outlined{color:rgb(var(--lsd-text-primary));}.lsd-badge--disabled{opacity:0.3;cursor:initial;pointer-events:none;}</style><style data-emotion="css-global rlst54">.lsd-radio-button{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-radio-button__input{opacity:0;position:absolute;left:0;top:0;padding:0;margin:0;width:100%;height:100%;}.lsd-radio-button:not(.lsd-radio-button--disabled):hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-radio-button:not(.lsd-radio-button--disabled) .lsd-radio-button__input{cursor:pointer;}.lsd-radio-button--disabled{opacity:0.34;}.lsd-radio-button__label{margin-left:18px;}.lsd-radio-button--large .lsd-radio-button__label{margin-left:18px;}.lsd-radio-button--medium .lsd-radio-button__label{margin-left:14px;}.lsd-radio-button--small .lsd-radio-button__label{margin-left:12px;}</style><style data-emotion="css-global mo7h6o">.lsd-radio-button-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:6px;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-radio-button-group__label{margin-bottom:6px;}</style><style data-emotion="css-global amncrr">.lsd-table{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-table>.lsd-table-header{margin-bottom:-1px;}</style><style data-emotion="css-global 1fkbozr">.lsd-table-header{box-sizing:border-box;border:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 1fb1r54">.lsd-table-body table{border-collapse:collapse;text-align:center;table-layout:fixed;width:100%;height:auto;}.lsd-table-body table tr:first-of-type td label:has(input[type='radio']){display:none;}.lsd-table-body__toolbar{box-sizing:border-box;padding:10px;border:1px solid rgb(var(--lsd-border-primary));border-bottom:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}</style><style data-emotion="css-global 607rj8">.lsd-table-item{border:1px solid rgb(var(--lsd-border-primary));}.lsd-table-item:has(> label){width:40px;}.lsd-table-item:has(> label) input{position:relative;width:14px;height:14px;margin:auto;}.lsd-table-item:has(> label) span{margin-left:14px!important;}.lsd-table-item--large{padding:10px;}.lsd-table-item--medium{padding:6px 8px;}.lsd-table-item--small{padding:6px;}</style><style data-emotion="css-global 1vlh57l">.lsd-table-row{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}</style><style data-emotion="css-global 1fw5y3v">.lsd-number-input{width:auto;box-sizing:border-box;}.lsd-number-input__main-container:hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-number-input--error .lsd-number-input__main-container{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-number-input__label{display:block;}.lsd-number-input__plus-minus-icons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-number-input__input-container{box-sizing:border-box;border:1px solid rgb(var(--lsd-border-primary));border-left:0px;border-right:0px;}.lsd-number-input__error-icon{cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:10px 8px;}.lsd-number-input__input-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-number-input--disabled{opacity:0.34;}.lsd-number-input__main-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-number-input__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;text-align:center;padding:0 4px;}.lsd-number-input__input::-webkit-inner-spin-button{display:none;-webkit-appearance:none;}.lsd-number-input__input:hover{outline:none;}.lsd-number-input__supporting-text{position:absolute;}.lsd-number-input--large .lsd-number-input__label{margin:0 0 6px 18px;}.lsd-number-input--large .lsd-number-input__input-container{height:40px;}.lsd-number-input--large .lsd-number-input__input{width:62px;}.lsd-number-input--large .lsd-number-input__plus-minus-icons{height:40px;width:40px;}.lsd-number-input--large .lsd-number-input__supporting-text{margin:6px 18px 0 18px;}.lsd-number-input--medium .lsd-number-input__label{margin:0 0 6px 14px;}.lsd-number-input--medium .lsd-number-input__input-container{height:32px;}.lsd-number-input--medium .lsd-number-input__input{width:58px;}.lsd-number-input--medium .lsd-number-input__plus-minus-icons{height:32px;width:32px;}.lsd-number-input--medium .lsd-number-input__supporting-text{margin:6px 14px 0 14px;}.lsd-number-input--small .lsd-number-input__label{margin:0 0 6px 12px;}.lsd-number-input--small .lsd-number-input__input-container{height:28px;}.lsd-number-input--small .lsd-number-input__input{width:50px;}.lsd-number-input--small .lsd-number-input__plus-minus-icons{height:28px;width:28px;}.lsd-number-input--small .lsd-number-input__supporting-text{margin:6px 12px 0 12px;}</style><style data-emotion="css-global 12rmo7o">.lsd-modal{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0, 0, 0, 0.5);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;z-index:9999;}.lsd-modal__container{position:relative;background:rgb(var(--lsd-surface-primary));padding:20px;max-width:90%;box-sizing:border-box;border:1px solid rgb(var(--lsd-border-primary));}.lsd-modal__header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-modal__close-icon{position:absolute;top:8px;right:8px;cursor:pointer;}.lsd-modal__title-and-subtitle-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-modal--large .lsd-modal__container{min-width:960px;}.lsd-modal--medium .lsd-modal__container{min-width:768px;}.lsd-modal--small .lsd-modal__container{min-width:614px;}.lsd-modal--extra-small .lsd-modal__container{min-width:490px;}</style><style data-emotion="css-global 1k7gzc">.lsd-modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}</style><style data-emotion="css-global 1b9t8so">.lsd-modal-body{margin:18px 0;}</style><style data-emotion="css-global dyud2a">.lsd-date-picker{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-date-picker__calendar{border-top:none!important;}.lsd-date-picker--large .lsd-date-field--large{width:318px;}.lsd-date-picker--medium .lsd-date-field--medium{width:290px;}.lsd-date-picker--small .lsd-date-field--small{width:262px;}</style><style data-emotion="css-global olq3nk">.lsd-date-field{width:auto;box-sizing:border-box;}.lsd-date-field__label{display:block;}.lsd-date-field__input-container__icon{position:absolute;right:0;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:rgb(var(--lsd-surface-primary));}.lsd-date-field__input-container__icon:focus{background:blue;background-color:pink;border:1px solid rgb(var(--lsd-border-primary));}.lsd-date-field__input-container__no-icon{position:absolute;right:0;background-color:rgb(var(--lsd-surface-primary));padding:12px;}.lsd-date-field--outlined{border:1px solid rgb(var(--lsd-border-primary));}.lsd-date-field--underlined{border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-date-field__input-container{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-date-field--disabled{opacity:0.34;}.lsd-date-field__input-container__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;width:100%;opacity:0.4;-webkit-transition:opacity 0.2s ease-in-out;transition:opacity 0.2s ease-in-out;}.lsd-date-field__input-container__input::-webkit-inner-spin-button,.lsd-date-field__input-container__input::-webkit-calendar-picker-indicator{display:none;-webkit-appearance:none;}.lsd-date-field__input-container__input:hover{outline:none;}.lsd-date-field__supporting-text{position:absolute;}.lsd-date-field--large{width:208px;}.lsd-date-field--large .lsd-date-field__label{margin:0 0 6px 18px;}.lsd-date-field--large .lsd-date-field__input-container{height:40px;}.lsd-date-field--large .lsd-date-field__input-container__input{padding:9px 0px 9px 17px;}.lsd-date-field--large .lsd-date-field__input-container__icon{padding:12px 13px;}.lsd-date-field--large .lsd-date-field__supporting-text{margin:6px 18px 0 18px;}.lsd-date-field--medium{width:188px;}.lsd-date-field--medium .lsd-date-field__label{margin:0 0 6px 14px;}.lsd-date-field--medium .lsd-date-field__input-container{height:32px;}.lsd-date-field--medium .lsd-date-field__input-container__input{padding:5px 11px 5px 13px;}.lsd-date-field--medium .lsd-date-field__input-container__icon{padding:8px 11px;}.lsd-date-field--medium .lsd-date-field__supporting-text{margin:6px 14px 0 14px;}.lsd-date-field--small{width:164px;}.lsd-date-field--small .lsd-date-field__label{margin:0 0 6px 12px;}.lsd-date-field--small .lsd-date-field__input-container{height:28px;}.lsd-date-field--small .lsd-date-field__input-container__input{padding:5px 9px 5px 11px;font-size:12px;}.lsd-date-field--small .lsd-date-field__input-container__icon{padding:6px 9px;}.lsd-date-field--small .lsd-date-field__supporting-text{margin:6px 12px 0 12px;}.lsd-date-field__input-container__input:invalid,.lsd-date-field__input-container__input--filled{color:rgb(var(--lsd-border-primary));opacity:1;}.lsd-date-field--error .lsd-date-field__input-container__input::-webkit-datetime-edit-year-field,.lsd-date-field--error .lsd-date-field__input-container__input::-webkit-datetime-edit-month-field,.lsd-date-field--error .lsd-date-field__input-container__input::-webkit-datetime-edit-day-field{-webkit-text-decoration:line-through;text-decoration:line-through;}@supports not selector(::-webkit-datetime-edit-day-field){.lsd-date-field--error .lsd-date-field__input-container__input{-webkit-text-decoration:line-through;text-decoration:line-through;}}</style><style data-emotion="css-global 1gjtao4">.lsd-calendar{border:1px solid rgb(var(--lsd-border-primary));visibility:hidden;position:absolute!important;top:0;left:0;opacity:0;visibility:hidden;margin:0;padding:0;box-sizing:border-box;background:rgb(var(--lsd-surface-primary));-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.lsd-calendar-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:8px;}.lsd-calendar--open{opacity:1;visibility:visible;}.lsd-calendar-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:32px;margin-bottom:8px;}.lsd-calendar__week_day{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;aspect-ratio:1/1;margin-bottom:4px;}.lsd-calendar__change-year{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:2px 0xp 2px 8px;gap:6px;border:1px solid transparent;}.lsd-calendar__change-year--active .lsd-calendar__year-and-icon{border:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar__change-year-icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border:none;}.lsd-calendar-month{margin-right:8px;}.lsd-calendar__month-and-year{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}.lsd-calendar-day__container{cursor:pointer;background:transparent;position:relative;box-sizing:border-box;border:1px solid transparent;}.lsd-calendar-day{aspect-ratio:1/1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-calendar-day:hover{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgb(var(--lsd-border-primary));}.lsd-calendar-day label:hover{cursor:pointer;}.lsd-calendar-day--selected{border:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar-day--disabled{opacity:0.3;cursor:default;}.lsd-calendar-day__today_indicator{position:absolute;left:50%;-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);bottom:2px;}.lsd-calendar--disabled{pointer-events:none;border:1px solid rgba(var(--lsd-border-primary), 0.3);}.lsd-calendar--disabled label{opacity:0.3;}.lsd-calendar--disabled .lsd-calendar__button{opacity:0.3;}.lsd-calendar--disabled .lsd-calendar-day--selected{opacity:0.3;}.lsd-calendar__button{border:1px solid rgb(var(--lsd-border-primary));cursor:pointer;background:transparent;width:32px;height:32px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;position:absolute;}.lsd-calendar__next-month-button{top:8px;right:8px;}.lsd-calendar__previous-month-button{top:8px;left:8px;}.lsd-calendar-day--border-left{border-left:1px double rgb(var(--lsd-border-primary));}.lsd-calendar-day--border-right{border-right:1px double rgb(var(--lsd-border-primary));}.lsd-calendar-day--border-left-and-right{border-left:1px double rgb(var(--lsd-border-primary));border-right:1px double rgb(var(--lsd-border-primary));}.lsd-calendar-day--border-top-and-bottom{border-top:1px double rgb(var(--lsd-border-primary));border-bottom:1px double rgb(var(--lsd-border-primary));}.lsd-calendar__month-table{border-collapse:collapse;}.lsd-calendar__year-dropdown{box-sizing:border-box;position:absolute;top:100%;left:0;max-height:200px;overflow-y:auto;width:100%;border:1px solid rgb(var(--lsd-border-primary));border-top:none;z-index:1;}.lsd-calendar__year-dropdown .lsd-calendar-year{border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar__year-dropdown--hidden{visibility:hidden;}.lsd-calendar-year{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-transition:background-color 0.2s;transition:background-color 0.2s;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:rgb(var(--lsd-surface-primary));}.lsd-calendar-year:hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-calendar__year-and-icon{border:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar--large .lsd-calendar-year{padding:6px 0px 6px 14px;}.lsd-calendar--large .lsd-calendar__change-year-icon-container{width:32px;}.lsd-calendar--medium .lsd-calendar-year{padding:6px 0px 6px 12px;}.lsd-calendar--medium .lsd-calendar__change-year-icon-container{width:28px;}.lsd-calendar--small .lsd-calendar-year{padding:6px 0px 6px 12px;}.lsd-calendar--small .lsd-calendar__change-year-icon-container{width:28px;}</style><style data-emotion="css-global dlrd7d">.lsd-toast{box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:rgb(var(--lsd-surface-primary));border:1px solid rgb(var(--lsd-border-primary));padding:8px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;}.lsd-toast__inline-button-container{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-toast__column-button-container{margin-top:18px;margin-bottom:6px;}.lsd-toast__inline-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}.lsd-toast__column-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-toast__text-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;color:rgb(var(--lsd-text-secondary));padding-left:12px;}.lsd-toast__title{position:relative;}.lsd-toast__information{margin-top:4px;}.lsd-toast__button-container{min-height:28px;min-width:60px;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;padding:0px 12px;}.lsd-toast__close-button{margin-bottom:auto;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;height:28px;width:28px;margin-left:auto;}.lsd-toast__column-icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;margin-bottom:auto;position:relative;top:4px;padding-left:4px;}.lsd-toast__inline-icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;padding-left:4px;}.lsd-toast__icon{position:relative;}.lsd-toast--large{width:364px;}.lsd-toast--medium{width:336px;}.lsd-toast--small{width:296px;}.lsd-toast--small .lsd-toast__icon{top:0px;}</style><style data-emotion="css-global 5wlfwk">.lsd-toast-provider__toast-container{position:fixed;-webkit-transition:all 230ms cubic-bezier(0.21, 1.02, 0.73, 1);transition:all 230ms cubic-bezier(0.21, 1.02, 0.73, 1);z-index:9999;}.lsd-toast-provider__toast--top-left,.lsd-toast-provider__toast--top-center,.lsd-toast-provider__toast--top-right{top:0;}.lsd-toast-provider__toast--bottom-left,.lsd-toast-provider__toast--bottom-center,.lsd-toast-provider__toast--bottom-right{bottom:0;}.lsd-toast-provider__toast--top-center,.lsd-toast-provider__toast--bottom-center{left:50%;}.lsd-toast-provider__toast--top-right,.lsd-toast-provider__toast--bottom-right{right:0;}</style><style data-emotion="css-global 9yw6e1">.lsd-button-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}.lsd-button-group >*:not(:last-child).lsd-button--outlined,.lsd-button-group >*:not(:last-child) .lsd-button--outlined{border-right:none;}</style><style data-emotion="css-global 17u9w7w">.lsd-date-range-picker{box-sizing:border-box;}.lsd-date-range-picker .lsd-date-field--outlined{border:none;}.lsd-date-range-picker .lsd-date-field__input-container__icon{padding:8px;}.lsd-date-range-picker__label{display:block;}.lsd-date-range-picker__input-container{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;}.lsd-date-picker__calendar{border-top:none!important;}.lsd-date-picker__calendar .lsd-tooltip-base__arrow-tip{-webkit-transition:left 0.2s ease-in-out;transition:left 0.2s ease-in-out;}.lsd-date-range-picker--calendar-open .lsd-date-range-picker__input-container{border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-date-range-picker__icon{cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding:0 10px;}.lsd-date-range-picker--disabled{opacity:0.3;}.lsd-date-range-picker__supporting-text{position:absolute;}.lsd-date-range-picker--large{width:318px;}.lsd-date-range-picker--large .lsd-date-field--large{width:156px;}.lsd-date-range-picker--large .lsd-date-field__input-container__input{padding-right:0;}.lsd-date-range-picker--large .lsd-date-field__input-container__icon{padding:11px 12px;}.lsd-date-range-picker--large .lsd-date-range-picker__label{margin:0 0 6px 18px;}.lsd-date-range-picker--large .lsd-date-range-picker__input-container{height:40px;}.lsd-date-range-picker--large .lsd-date-range-picker__supporting-text{margin:6px 18px 0 18px;}.lsd-date-range-picker--medium{width:290px;}.lsd-date-range-picker--medium .lsd-date-field--medium{width:142px;}.lsd-date-range-picker--medium .lsd-date-field__input-container__input{padding-right:0;}.lsd-date-range-picker--medium .lsd-date-field__input-container__icon{padding:7px 8px;}.lsd-date-range-picker--medium .lsd-date-range-picker__label{margin:0 0 6px 14px;}.lsd-date-range-picker--medium .lsd-date-range-picker__input-container{height:32px;}.lsd-date-range-picker--medium .lsd-date-range-picker__supporting-text{margin:6px 14px 0 14px;}.lsd-date-range-picker--small{width:262px;}.lsd-date-range-picker--small .lsd-date-field--small{width:128px;}.lsd-date-range-picker--small .lsd-date-field__input-container__input{padding-right:0;}.lsd-date-range-picker--small .lsd-date-field__input-container__icon{padding:5px 7px;}.lsd-date-range-picker--small .lsd-date-range-picker__label{margin:0 0 6px 12px;}.lsd-date-range-picker--small .lsd-date-range-picker__input-container{height:28px;}.lsd-date-range-picker--small .lsd-date-range-picker__supporting-text{margin:6px 12px 0 12px;}.lsd-date-range-picker__separator{margin-left:3px;width:1px;height:100%;}.lsd-date-range-picker__separator{border-left:1px solid transparent;}.lsd-date-range-picker--outlined{border:1px solid rgb(var(--lsd-border-primary));}.lsd-date-range-picker--outlined .lsd-date-range-picker__separator{border-left:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 19d282h">.lsd-tooltip-base{border:1px solid rgb(var(--lsd-border-primary));position:relative;}.lsd-tooltip-base__arrow-tip{border:1px solid rgb(var(--lsd-border-primary));position:absolute;background:rgb(var(--lsd-surface-primary));}.lsd-tooltip-base__content{background:rgb(var(--lsd-surface-primary));width:100%;height:100%;position:relative;z-index:1;}</style><style data-emotion="css-global js1ujt">html:not([data-theme]){--lsd-display1-fontSize:5.5rem;--lsd-display1-fontWeight:normal;--lsd-display1-lineHeight:6rem;--lsd-display2-fontSize:4rem;--lsd-display2-fontWeight:normal;--lsd-display2-lineHeight:4.5rem;--lsd-display3-fontSize:3.5rem;--lsd-display3-fontWeight:normal;--lsd-display3-lineHeight:4rem;--lsd-display4-fontSize:3rem;--lsd-display4-fontWeight:normal;--lsd-display4-lineHeight:3.5rem;--lsd-h1-fontSize:2.5rem;--lsd-h1-fontWeight:normal;--lsd-h1-lineHeight:3rem;--lsd-h2-fontSize:2rem;--lsd-h2-fontWeight:normal;--lsd-h2-lineHeight:2.5rem;--lsd-h3-fontSize:1.75rem;--lsd-h3-fontWeight:normal;--lsd-h3-lineHeight:2.25rem;--lsd-h4-fontSize:1.5rem;--lsd-h4-fontWeight:normal;--lsd-h4-lineHeight:2rem;--lsd-h5-fontSize:1.25rem;--lsd-h5-fontWeight:normal;--lsd-h5-lineHeight:1.75rem;--lsd-h6-fontSize:1rem;--lsd-h6-fontWeight:normal;--lsd-h6-lineHeight:1.5rem;--lsd-subtitle1-fontSize:1.125rem;--lsd-subtitle1-fontWeight:normal;--lsd-subtitle1-lineHeight:1.5rem;--lsd-subtitle2-fontSize:1rem;--lsd-subtitle2-fontWeight:normal;--lsd-subtitle2-lineHeight:1.5rem;--lsd-subtitle3-fontSize:0.875rem;--lsd-subtitle3-fontWeight:normal;--lsd-subtitle3-lineHeight:1.25rem;--lsd-subtitle4-fontSize:0.75rem;--lsd-subtitle4-fontWeight:normal;--lsd-subtitle4-lineHeight:1rem;--lsd-body1-fontSize:1rem;--lsd-body1-fontWeight:normal;--lsd-body1-lineHeight:1.5rem;--lsd-body2-fontSize:0.875rem;--lsd-body2-fontWeight:normal;--lsd-body2-lineHeight:1.25rem;--lsd-body3-fontSize:0.75rem;--lsd-body3-fontWeight:normal;--lsd-body3-lineHeight:1rem;--lsd-label1-fontSize:0.875rem;--lsd-label1-fontWeight:normal;--lsd-label1-lineHeight:1.25rem;--lsd-label2-fontSize:0.75rem;--lsd-label2-fontWeight:normal;--lsd-label2-lineHeight:1rem;--lsd-typography-generic-font-family:sans-serif;--lsd-theme-primary:0,0,0;--lsd-theme-secondary:255,255,255;--lsd-surface-primary:255,255,255;--lsd-surface-secondary:0,0,0;--lsd-border-primary:0,0,0;--lsd-border-secondary:255,255,255;--lsd-icon-primary:0,0,0;--lsd-icon-secondary:255,255,255;--lsd-text-primary:0,0,0;--lsd-text-secondary:255,255,255;--lsd-text-tertiary:0,0,0,0.34;--lsd-spacing-4:4px;--lsd-spacing-8:8px;--lsd-spacing-16:16px;--lsd-spacing-24:24px;--lsd-spacing-32:32px;--lsd-spacing-40:40px;--lsd-spacing-64:64px;--lsd-spacing-80:80px;--lsd-spacing-96:96px;--lsd-spacing-120:120px;}html[data-theme='light']{--lsd-display1-fontSize:5.5rem;--lsd-display1-fontWeight:normal;--lsd-display1-lineHeight:6rem;--lsd-display2-fontSize:4rem;--lsd-display2-fontWeight:normal;--lsd-display2-lineHeight:4.5rem;--lsd-display3-fontSize:3.5rem;--lsd-display3-fontWeight:normal;--lsd-display3-lineHeight:4rem;--lsd-display4-fontSize:3rem;--lsd-display4-fontWeight:normal;--lsd-display4-lineHeight:3.5rem;--lsd-h1-fontSize:2.5rem;--lsd-h1-fontWeight:normal;--lsd-h1-lineHeight:3rem;--lsd-h2-fontSize:2rem;--lsd-h2-fontWeight:normal;--lsd-h2-lineHeight:2.5rem;--lsd-h3-fontSize:1.75rem;--lsd-h3-fontWeight:normal;--lsd-h3-lineHeight:2.25rem;--lsd-h4-fontSize:1.5rem;--lsd-h4-fontWeight:normal;--lsd-h4-lineHeight:2rem;--lsd-h5-fontSize:1.25rem;--lsd-h5-fontWeight:normal;--lsd-h5-lineHeight:1.75rem;--lsd-h6-fontSize:1rem;--lsd-h6-fontWeight:normal;--lsd-h6-lineHeight:1.5rem;--lsd-subtitle1-fontSize:1.125rem;--lsd-subtitle1-fontWeight:normal;--lsd-subtitle1-lineHeight:1.5rem;--lsd-subtitle2-fontSize:1rem;--lsd-subtitle2-fontWeight:normal;--lsd-subtitle2-lineHeight:1.5rem;--lsd-subtitle3-fontSize:0.875rem;--lsd-subtitle3-fontWeight:normal;--lsd-subtitle3-lineHeight:1.25rem;--lsd-subtitle4-fontSize:0.75rem;--lsd-subtitle4-fontWeight:normal;--lsd-subtitle4-lineHeight:1rem;--lsd-body1-fontSize:1rem;--lsd-body1-fontWeight:normal;--lsd-body1-lineHeight:1.5rem;--lsd-body2-fontSize:0.875rem;--lsd-body2-fontWeight:normal;--lsd-body2-lineHeight:1.25rem;--lsd-body3-fontSize:0.75rem;--lsd-body3-fontWeight:normal;--lsd-body3-lineHeight:1rem;--lsd-label1-fontSize:0.875rem;--lsd-label1-fontWeight:normal;--lsd-label1-lineHeight:1.25rem;--lsd-label2-fontSize:0.75rem;--lsd-label2-fontWeight:normal;--lsd-label2-lineHeight:1rem;--lsd-typography-generic-font-family:sans-serif;--lsd-theme-primary:0,0,0;--lsd-theme-secondary:255,255,255;--lsd-surface-primary:255,255,255;--lsd-surface-secondary:0,0,0;--lsd-border-primary:0,0,0;--lsd-border-secondary:255,255,255;--lsd-icon-primary:0,0,0;--lsd-icon-secondary:255,255,255;--lsd-text-primary:0,0,0;--lsd-text-secondary:255,255,255;--lsd-text-tertiary:0,0,0,0.34;--lsd-spacing-4:4px;--lsd-spacing-8:8px;--lsd-spacing-16:16px;--lsd-spacing-24:24px;--lsd-spacing-32:32px;--lsd-spacing-40:40px;--lsd-spacing-64:64px;--lsd-spacing-80:80px;--lsd-spacing-96:96px;--lsd-spacing-120:120px;}html[data-theme='dark']{--lsd-display1-fontSize:5.5rem;--lsd-display1-fontWeight:normal;--lsd-display1-lineHeight:6rem;--lsd-display2-fontSize:4rem;--lsd-display2-fontWeight:normal;--lsd-display2-lineHeight:4.5rem;--lsd-display3-fontSize:3.5rem;--lsd-display3-fontWeight:normal;--lsd-display3-lineHeight:4rem;--lsd-display4-fontSize:3rem;--lsd-display4-fontWeight:normal;--lsd-display4-lineHeight:3.5rem;--lsd-h1-fontSize:2.5rem;--lsd-h1-fontWeight:normal;--lsd-h1-lineHeight:3rem;--lsd-h2-fontSize:2rem;--lsd-h2-fontWeight:normal;--lsd-h2-lineHeight:2.5rem;--lsd-h3-fontSize:1.75rem;--lsd-h3-fontWeight:normal;--lsd-h3-lineHeight:2.25rem;--lsd-h4-fontSize:1.5rem;--lsd-h4-fontWeight:normal;--lsd-h4-lineHeight:2rem;--lsd-h5-fontSize:1.25rem;--lsd-h5-fontWeight:normal;--lsd-h5-lineHeight:1.75rem;--lsd-h6-fontSize:1rem;--lsd-h6-fontWeight:normal;--lsd-h6-lineHeight:1.5rem;--lsd-subtitle1-fontSize:1.125rem;--lsd-subtitle1-fontWeight:normal;--lsd-subtitle1-lineHeight:1.5rem;--lsd-subtitle2-fontSize:1rem;--lsd-subtitle2-fontWeight:normal;--lsd-subtitle2-lineHeight:1.5rem;--lsd-subtitle3-fontSize:0.875rem;--lsd-subtitle3-fontWeight:normal;--lsd-subtitle3-lineHeight:1.25rem;--lsd-subtitle4-fontSize:0.75rem;--lsd-subtitle4-fontWeight:normal;--lsd-subtitle4-lineHeight:1rem;--lsd-body1-fontSize:1rem;--lsd-body1-fontWeight:normal;--lsd-body1-lineHeight:1.5rem;--lsd-body2-fontSize:0.875rem;--lsd-body2-fontWeight:normal;--lsd-body2-lineHeight:1.25rem;--lsd-body3-fontSize:0.75rem;--lsd-body3-fontWeight:normal;--lsd-body3-lineHeight:1rem;--lsd-label1-fontSize:0.875rem;--lsd-label1-fontWeight:normal;--lsd-label1-lineHeight:1.25rem;--lsd-label2-fontSize:0.75rem;--lsd-label2-fontWeight:normal;--lsd-label2-lineHeight:1rem;--lsd-typography-generic-font-family:sans-serif;--lsd-theme-primary:255,255,255;--lsd-theme-secondary:0,0,0;--lsd-surface-primary:0,0,0;--lsd-surface-secondary:255,255,255;--lsd-border-primary:255,255,255;--lsd-border-secondary:0,0,0;--lsd-icon-primary:255,255,255;--lsd-icon-secondary:0,0,0;--lsd-text-primary:255,255,255;--lsd-text-secondary:0,0,0;--lsd-text-tertiary:255,255,255,0.34;--lsd-spacing-4:4px;--lsd-spacing-8:8px;--lsd-spacing-16:16px;--lsd-spacing-24:24px;--lsd-spacing-32:32px;--lsd-spacing-40:40px;--lsd-spacing-64:64px;--lsd-spacing-80:80px;--lsd-spacing-96:96px;--lsd-spacing-120:120px;}</style><div class="root_QACb"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top navbarHideable_OoEf"><div class="navbar__inner"><div class="navbar__left"><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--light_BL8e" height="26"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--dark_OvIx" height="26"></div><b class="navbar__title text--truncate"></b></a></div><div class="navbar__left-items"></div><div class="navbar__right-items"><div class="iconButtonGroup_ktNv lsd-icon-button-group lsd-icon-button-group--medium lsd-icon-button-group--outlined"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="main-wrapper mainWrapper_z2l0 docsWrapper_BCFX"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type="button"></button><div class="docPage__5DB"><aside class="theme-doc-sidebar-container docSidebarContainer_b6E3"><div class="sidebarViewport_Xe31"><div class="sidebar_UEyd sidebarWithHideableNavbar__00c"><a tabindex="-1" class="sidebarLogo_Ydl9" href="/"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--light_BL8e" height="26"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--dark_OvIx" height="26"><b></b></a><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_NjKY"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/">Status RFCs</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist" aria-expanded="false" href="/status/deprecated/3rd-party"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="chevron_How5 lsd-icon lsd-icon--small lsd-icon--filled"><path d="M3.5 8.33875L4.3225 9.16125L7 6.48959L9.6775 9.16125L10.5 8.33875L7 4.83875L3.5 8.33875Z" fill="black"></path></svg><span class="lsd-typography lsd-typography--body2 lsd-typography--primary">deprecated</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist" aria-expanded="false" href="/status/raw/simple-scaling"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="chevron_How5 lsd-icon lsd-icon--small lsd-icon--filled"><path d="M3.5 8.33875L4.3225 9.16125L7 6.48959L9.6775 9.16125L10.5 8.33875L7 4.83875L3.5 8.33875Z" fill="black"></path></svg><span class="lsd-typography lsd-typography--body2 lsd-typography--primary">raw</span></a></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/24/curation">24/STATUS-CURATION</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/28/featuring">28/STATUS-FEATURING</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/55/1to1-chat">55/STATUS-1TO1-CHAT</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/56/communities">56/STATUS-COMMUNITIES</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/61/community-history-service">61/STATUS-Community-History-Service</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/62/payloads">62/STATUS-PAYLOADS</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/63/keycard-usage">63/STATUS-Keycard-Usage</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/status/65/account-address">65/STATUS-ACCOUNT-ADDRESS</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" href="/status/71/push-notification-server">71/STATUS-PUSH-NOTIFICATION-SERVER</a></li></ul></nav></div></div></aside><main class="docMainContainer_gTbr"><div class="container padding-top--md padding-bottom--lg"><div class="row docItemGrid_SzoZ"><div class="docItemCol_F52z"><div class="docItemContainer_hrrU"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_RLvU" aria-label="Breadcrumbs"><ul class="breadcrumbs" itemscope="" itemtype="https://schema.org/BreadcrumbList"><a class="breadcrumbs__item" href="/status"><span class="lsd-typography lsd-typography--body3">Home</span></a><li itemscope="" itemprop="itemListElement" itemtype="https://schema.org/ListItem" class="breadcrumbs__item breadcrumbs__item--active"><span class="lsd-typography lsd-typography--body3 breadcrumbs__link" itemprop="name">71/STATUS-PUSH-NOTIFICATION-SERVER</span><meta itemprop="position" content="1"></li></ul></nav><div class="theme-doc-markdown markdown"><header><h1>71/STATUS-PUSH-NOTIFICATION-SERVER</h1><div class="tocMobile_imaF"><div class="tocCollapsible_ROek theme-doc-toc-mobile tocMobile_ITEo"><button type="button" class="clean-btn tocCollapsibleButton_dxRj"><div></div><span class="lsd-typography lsd-typography--body2">On this page</span><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="lsd-icon lsd-icon--small lsd-icon--filled"><path d="M10.5 5.66125L9.6775 4.83875L7 7.51041L4.3225 4.83874L3.5 5.66125L7 9.16125L10.5 5.66125Z" fill="black"></path></svg></button></div></div></header><ul><li>Status: draft</li><li>Category: Standards Track</li><li>Editor: Jimmy Debe <<a href="mailto:jimmy@status.im" target="_blank" rel="noopener noreferrer">jimmy@status.im</a>></li><li>Contributors:<ul><li>Andrea Maria Piana <<a href="mailto:andreap@status.im" target="_blank" rel="noopener noreferrer">andreap@status.im</a>></li></ul></li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="abstract">Abstract<a href="#abstract" class="hash-link" aria-label="Direct link to Abstract" title="Direct link to Abstract"></a></h2><p>A push notification server implementation for IOS devices and Android devices.
|
||
This specification provides a set of methods that allow clients
|
||
to use push notification services in mobile environments.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="background">Background<a href="#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background"></a></h2><p>Push notification for iOS and
|
||
Android devices can only be implemented by relying on
|
||
<a href="https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1" target="_blank" rel="noopener noreferrer">APN</a>,
|
||
Apple Push Notification, service for iOS or
|
||
<a href="https://firebase.google.com/" target="_blank" rel="noopener noreferrer">Firebase</a> for Android.</p><p>For some Android devices, foreground services are restricted,
|
||
requiring a user to grant authorization to applications
|
||
to use foreground notifications.
|
||
Apple iOS devices restrict notifications to
|
||
a few internal functions that every application can not use.
|
||
Applications on iOS can request execution time when they are in the background.
|
||
This has a limited set of use cases for example,
|
||
it will not schedule any time if the application was closed with force quit.
|
||
Requesting execution time is not responsive enough to
|
||
implement a push notification system.
|
||
Status provides a set of methods to acheive push notification services.</p><p>Since this can not be safely implemented in a privacy-preserving manner,
|
||
clients need to be given an option to opt-in to receive and send push notifications.
|
||
They are disabled by default.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="specification">Specification<a href="#specification" class="hash-link" aria-label="Direct link to Specification" title="Direct link to Specification"></a></h2><p>The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”,
|
||
“SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and
|
||
“OPTIONAL” in this document are to be interpreted as described in <a href="https://www.ietf.org/rfc/rfc2119.txt" target="_blank" rel="noopener noreferrer">2119</a>.</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="definitions">Definitions<a href="#definitions" class="hash-link" aria-label="Direct link to Definitions" title="Direct link to Definitions"></a></h3><table><thead><tr><th>Terminology</th><th>Description</th></tr></thead><tbody><tr><td>client</td><td>A node that implements the Status specifications.</td></tr><tr><td>user</td><td>The owner of a device that runs a client.</td></tr><tr><td>server</td><td>A service that performs push notifications.</td></tr><tr><td>Waku-Store</td><td>A Waku node that decides to provide functionality to store messages permanently and deliver the messages to requesting clients. As described in <a href="/waku/standards/core/13/store">13/WAKU-STORE</a> specification.</td></tr></tbody></table><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="server-components">Server Components<a href="#server-components" class="hash-link" aria-label="Direct link to Server Components" title="Direct link to Server Components"></a></h3><table><thead><tr><th>Components</th><th>Description</th></tr></thead><tbody><tr><td>gorush Instance</td><td>Only used by push notification servers and MUST be publicly available.</td></tr><tr><td>Push Notification Server</td><td>Used by clients to register for receiving and sending notifications.</td></tr><tr><td>Registering Client</td><td>A client that wants to receive push notifications.</td></tr><tr><td>Sending Client</td><td>A client that wants to send push notifications.</td></tr></tbody></table><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="requirements">Requirements<a href="#requirements" class="hash-link" aria-label="Direct link to Requirements" title="Direct link to Requirements"></a></h3><p>The party releasing the app MUST possess a certificate
|
||
for the Apple Push Notification service and
|
||
it MUST run a <a href="https://github.com/appleboy/gorush" target="_blank" rel="noopener noreferrer">gorush</a>
|
||
publicly accessible server for sending the actual notification.
|
||
The party releasing the app MUST run its own <a href="https://github.com/appleboy/gorush" target="_blank" rel="noopener noreferrer">gorush</a>.</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="push-notification-server-flow">Push Notification Server Flow<a href="#push-notification-server-flow" class="hash-link" aria-label="Direct link to Push Notification Server Flow" title="Direct link to Push Notification Server Flow"></a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="registration-process">Registration Process<a href="#registration-process" class="hash-link" aria-label="Direct link to Registration Process" title="Direct link to Registration Process"></a></h4><p></p><div class="wrapper_SWrM active_qZD5"><img loading="lazy" alt="registration" src="/assets/images/registration-cc6fec7743be6c531d9b93203960114f.png" width="407" height="331" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><p></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="sending-and-receiving-notification-process">Sending and Receiving Notification Process<a href="#sending-and-receiving-notification-process" class="hash-link" aria-label="Direct link to Sending and Receiving Notification Process" title="Direct link to Sending and Receiving Notification Process"></a></h4><p></p><div class="wrapper_SWrM active_qZD5"><img loading="lazy" alt="notification" src="/assets/images/notification-03a7ab32603bbca7741c8513211468dd.png" width="518" height="607" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><p></p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="registering-client">Registering Client<a href="#registering-client" class="hash-link" aria-label="Direct link to Registering Client" title="Direct link to Registering Client"></a></h3><p>Registering a client with a push notification service.</p><ul><li><p>A client MAY register with one or
|
||
more push notification services in order to increase availability.</p></li><li><p>A client SHOULD make sure that all the notification services they registered with
|
||
have the same information about their tokens.</p></li><li><p>A <code>PNR message</code> (Push Notification Registration) MUST be sent to the
|
||
<a href="/waku/standards/application/54/x3dh-sessions">partitioned topic</a>
|
||
for the public key of the node, encrypted with this key.</p></li><li><p>The message MUST be wrapped in a
|
||
<a href="/status/62/payloads"><code>ApplicationMetadataMessage</code></a> with type set to <code>PUSH_NOTIFICATION_REGISTRATION</code>.</p></li><li><p>The marshaled protobuf payload MUST also be encrypted with AES-GCM
|
||
using the Diffie–Hellman key generated from the client and server identity.
|
||
This is done in order to ensure that the extracted key from the signature
|
||
will be considered invalid if it can’t decrypt the payload.</p></li></ul><p>The content of the message MUST contain the following <a href="https://developers.google.com/protocol-buffers/" target="_blank" rel="noopener noreferrer">protobuf record</a>:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationRegistration {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> enum TokenType {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> UNKNOWN_TOKEN_TYPE = 0;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> APN_TOKEN = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> FIREBASE_TOKEN = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> TokenType token_type = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string device_token = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string installation_id = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string access_token = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool enabled = 5;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> uint64 version = 6;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated bytes allowed_key_list = 7;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated bytes blocked_chat_list = 8;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool unregister = 9;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes grant = 10;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool allow_from_contacts_only = 11;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string apn_topic = 12;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool block_mentions = 13;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated bytes allowed_mentions_chat_list = 14;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p>A push notification server will handle the message according to the following rules:</p><ul><li><p>it MUST extract the public key of the sender from the signature and
|
||
verify that the payload can be decrypted successfully.</p></li><li><p>it MUST verify that <code>token_type</code> is supported.</p></li><li><p>it MUST verify that <code>device_token</code> is non empty.</p></li><li><p>it MUST verify that <code>installation_id</code> is non empty.</p></li><li><p>it MUST verify that <code>version</code> is non-zero and
|
||
greater than the currently stored version for the public key and
|
||
<code>installation_id</code> of the sender, if any.</p></li><li><p>it MUST verify that <code>grant</code> is non empty and according to the Grant Server specs.</p></li><li><p>it MUST verify that <code>access_token</code> is a valid uuid.</p></li><li><p>it MUST verify that <code>apn_topic</code> is set if token_type is APN_TOKEN.</p></li><li><p>The message MUST be wrapped in a
|
||
<a href="/status/62/payloads"><code>ApplicationMetadataMessage</code></a> with type set to <code>PUSH_NOTIFICATION_REGISTRATION_RESPONSE</code>.</p></li></ul><p>The payload of the response is:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationRegistrationResponse {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool success = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ErrorType error = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes request_id = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> enum ErrorType {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> UNKNOWN_ERROR_TYPE = 0;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> MALFORMED_MESSAGE = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> VERSION_MISMATCH = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> UNSUPPORTED_TOKEN_TYPE = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> INTERNAL_ERROR = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p>A client SHOULD listen for a response sent on the
|
||
<a href="/waku/standards/application/54/x3dh-sessions">partitioned topic</a>
|
||
that the key used to register.
|
||
If success is true the client has registered successfully.</p><p>If <code>success</code> is <code>false</code>:
|
||
> If <code>MALFORMED_MESSAGE</code> is returned,
|
||
the request SHOULD NOT be retried without ensuring that it is correctly formed.
|
||
> If <code>INTERNAL_ERROR</code> is returned, the request MAY be retried,
|
||
but the client MUST backoff exponentially.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="handle-errors">Handle Errors<a href="#handle-errors" class="hash-link" aria-label="Direct link to Handle Errors" title="Direct link to Handle Errors"></a></h4><ul><li><p>If the message can’t be decrypted, the message MUST be discarded.</p></li><li><p>If <code>token_type</code> is not supported, a response MUST be sent with <code>error</code> set to <code>UNSUPPORTED_TOKEN_TYPE</code>.</p></li><li><p>If <code>token</code>, <code>installation_id</code>, <code>device_tokens</code>, <code>version</code> are empty,
|
||
a response MUST be sent with <code>error</code> set to <code>MALFORMED_MESSAGE</code>.</p></li><li><p>If the <code>version</code> is equal or less than the currently stored <code>version</code>,
|
||
a response MUST be sent with <code>error</code> set to <code>VERSION_MISMATCH</code>.</p></li><li><p>If any other error occurs the <code>error</code> SHOULD be set to <code>INTERNAL_ERROR</code>.</p></li><li><p>If the response is successful <code>success</code> MUST be set to <code>true</code> otherwise
|
||
a response MUST be sent with <code>success</code> set to <code>false</code>.</p></li><li><p><code>request_id</code> SHOULD be set to the
|
||
<a href="https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf" target="_blank" rel="noopener noreferrer"><code>SHAKE-256</code></a>
|
||
of the encrypted payload.</p></li><li><p>The response MUST be sent on the
|
||
<a href="/waku/standards/application/54/x3dh-sessions">partitioned topic</a>
|
||
of the sender and MUST not be encrypted using
|
||
the secure transport to facilitate the usage of ephemeral keys.</p></li><li><p>If no response is returned, the request SHOULD be considered failed and
|
||
MAY be retried with the same server or a different one, but clients
|
||
MUST exponentially backoff after each trial.</p></li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="push-notification-server">Push Notification Server<a href="#push-notification-server" class="hash-link" aria-label="Direct link to Push Notification Server" title="Direct link to Push Notification Server"></a></h2><p>A node that handles receiving and sending push notifications for clients.</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="query-topic">Query Topic<a href="#query-topic" class="hash-link" aria-label="Direct link to Query Topic" title="Direct link to Query Topic"></a></h3><p>On successful registration the server MUST be listening to the topic derived from:
|
||
> <code>0x</code> + HexEncode(Shake256(CompressedClientPublicKey))</p><p>Using the topic derivation algorithm described here and listen for client queries.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="server-grant">Server Grant<a href="#server-grant" class="hash-link" aria-label="Direct link to Server Grant" title="Direct link to Server Grant"></a></h4><p>A client MUST authorize a push notification server to send them push notifications.
|
||
This is done by building a grant which is specific to a given client-server pair.
|
||
When receiving a grant,
|
||
the server MUST validate that the signature matches the registering client.</p><p>The grant is built as:</p><div class="language-js codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-js codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Signature(Keccak256(CompressedPublicKeyOfClient.CompressedPublicKeyOfServer.AccessToken), PrivateKeyOfClient)</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="unregistering-with-a-server">Unregistering with a Server<a href="#unregistering-with-a-server" class="hash-link" aria-label="Direct link to Unregistering with a Server" title="Direct link to Unregistering with a Server"></a></h4><ul><li>To unregister a client MUST send a <code>PushNotificationRegistration</code>
|
||
request as described above with <code>unregister</code> set to <code>true</code>,
|
||
or removing their device information.</li><li>The server MUST remove all data about this user if <code>unregistering</code> is <code>true</code>,
|
||
apart from the <code>hash</code> of the public key and
|
||
the <code>version</code> of the last options,
|
||
in order to make sure that old messages are not processed.</li><li>A client MAY unregister from a server on explicit logout
|
||
if multiple chat keys are used on a single device.</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="re-registering-with-a-server">Re-registering with a Server<a href="#re-registering-with-a-server" class="hash-link" aria-label="Direct link to Re-registering with a Server" title="Direct link to Re-registering with a Server"></a></h4><ul><li>A client SHOULD re-register with the node if the APN or FIREBASE token changes.</li><li>When re-registering a client SHOULD ensure
|
||
that it has the most up-to-date <code>PushNotificationRegistration</code> and
|
||
increment <code>version</code> if necessary.</li><li>Once re-registered, a client SHOULD advertise the changes.
|
||
Changing options is handled the same as re-registering.</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="advertising-a-server">Advertising a Server<a href="#advertising-a-server" class="hash-link" aria-label="Direct link to Advertising a Server" title="Direct link to Advertising a Server"></a></h4><p>Each user registered with one or more push notification servers
|
||
SHOULD advertise periodically the push notification services
|
||
they have registered with for each device they own.</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationQueryInfo {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string access_token = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string installation_id = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes public_key = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated bytes allowed_user_list = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes grant = 5;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> uint64 version = 6;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes server_public_key = 7;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">message ContactCodeAdvertisement {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated PushNotificationQueryInfo push_notification_info = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="handle-advertisement-message">Handle Advertisement Message<a href="#handle-advertisement-message" class="hash-link" aria-label="Direct link to Handle Advertisement Message" title="Direct link to Handle Advertisement Message"></a></h4><ul><li>The message MUST be wrapped in a
|
||
<a href="/status/62/payloads"><code>ApplicationMetadataMessage</code></a> with type set to <code>PUSH_NOTIFICATION_QUERY_INFO</code>.</li><li>If no filtering is done based on public keys,
|
||
the access token SHOULD be included in the advertisement.
|
||
Otherwise it SHOULD be left empty.</li><li>This SHOULD be advertised on the
|
||
<a href="/waku/standards/application/53/x3dh">contact code topic</a> and
|
||
SHOULD be coupled with normal contact-code advertisement.</li><li>When a user register or re-register with a push notification service,
|
||
their contact-code SHOULD be re-advertised.</li><li>Multiple servers MAY be advertised for the same installation_id
|
||
for redundancy reasons.</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="discovering-a-server">Discovering a Server<a href="#discovering-a-server" class="hash-link" aria-label="Direct link to Discovering a Server" title="Direct link to Discovering a Server"></a></h4><p>To discover a push notification service for a given user, their
|
||
<a href="/waku/standards/application/53/x3dh">contact code topic</a>
|
||
SHOULD be listened to.
|
||
A Waku-Store node can be queried for the specific topic
|
||
to retrieve the most up-to-date contact code.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="querying-a-server">Querying a Server<a href="#querying-a-server" class="hash-link" aria-label="Direct link to Querying a Server" title="Direct link to Querying a Server"></a></h4><p>If a token is not present in the latest advertisement for a user,
|
||
the server SHOULD be queried directly.</p><p>To query a server a message:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationQuery {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated bytes public_keys = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="handle-query-message">Handle Query Message<a href="#handle-query-message" class="hash-link" aria-label="Direct link to Handle Query Message" title="Direct link to Handle Query Message"></a></h4><ul><li>The message MUST be wrapped in a
|
||
<a href="/status/62/payloads"><code>ApplicationMetadataMessage</code></a> with type set to <code>PUSH_NOTIFICATION_QUERY</code>.</li><li>it MUST be sent to the server on the topic derived from the hashed public key
|
||
of the key we are querying,
|
||
<a href="#query-topic">as described above</a>.</li><li>An ephemeral key SHOULD be used and SHOULD NOT be encrypted using the <a href="/waku/standards/application/53/x3dh">secure transport</a>.</li></ul><p>If the server has information about the client a response MUST be sent:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationQueryInfo {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string access_token = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string installation_id = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes public_key = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated bytes allowed_user_list = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes grant = 5;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> uint64 version = 6;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes server_public_key = 7;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationQueryResponse {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated PushNotificationQueryInfo info = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes message_id = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool success = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="handle-query-response">Handle Query Response<a href="#handle-query-response" class="hash-link" aria-label="Direct link to Handle Query Response" title="Direct link to Handle Query Response"></a></h4><ul><li><p>A <code>PushNotificationQueryResponse</code> message MUST be wrapped in a
|
||
<a href="/status/62/payloads"><code>ApplicationMetadataMessage</code></a> with type set to <code>PUSH_NOTIFICATION_QUERY_RESPONSE</code>.
|
||
Otherwise a response MUST NOT be sent.</p></li><li><p>If <code>allowed_key_list</code> is not set <code>access_token</code> MUST be set
|
||
and <code>allowed_key_list</code> MUST NOT be set.</p></li><li><p>If <code>allowed_key_list</code> is set <code>allowed_key_list</code> MUST be set and
|
||
<code>access_token</code> MUST NOT be set.</p></li><li><p>If <code>access_token</code> is returned,
|
||
the <code>access_token</code> SHOULD be used to send push notifications.</p></li><li><p>If <code>allowed_key_list</code> are returned,
|
||
the client SHOULD decrypt each token by generating an <code>AES-GCM</code> symmetric key
|
||
from the Diffie–Hellman between the target client and itself.
|
||
If AES decryption succeeds,
|
||
it will return a valid <code>uuid</code> which is what is used for access_token.
|
||
The token SHOULD be used to send push notifications.</p></li><li><p>The response MUST be sent on the
|
||
<a href="/waku/standards/application/54/x3dh-sessions">partitioned topic</a>
|
||
of the sender and
|
||
MUST NOT be encrypted using the
|
||
<a href="/waku/standards/application/53/x3dh">secure transport</a>
|
||
to facilitate the usage of ephemeral keys.</p></li><li><p>On receiving a response,
|
||
a client MUST verify <code>grant</code> to ensure that the server
|
||
has been authorized to send push notification to a given client.</p></li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="sending-client">Sending Client<a href="#sending-client" class="hash-link" aria-label="Direct link to Sending Client" title="Direct link to Sending Client"></a></h3><p>Sending a push notification</p><ul><li><p>When sending a push notification,
|
||
only the <code>installation_id</code> for the devices targeted by the message SHOULD be used.</p></li><li><p>If a message is for all the user devices,
|
||
all the <code>installation_id</code> known to the client MAY be used.</p></li><li><p>The number of devices MAY be capped in order to reduce resource consumption.</p></li><li><p>At least 3 devices SHOULD be targeted, ordered by last activity.</p></li><li><p>For any device that a token is available, or that
|
||
a token is successfully queried,
|
||
a push notification message SHOULD be sent to the corresponding
|
||
push notification server.</p></li></ul><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotification {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string access_token = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string chat_id = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes public_key = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string installation_id = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes message = 5;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> PushNotificationType type = 6;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> enum PushNotificationType {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> UNKNOWN_PUSH_NOTIFICATION_TYPE = 0;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> MESSAGE = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> MENTION = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes author = 7;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationRequest {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated PushNotification requests = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes message_id = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="handle-notification-request">Handle Notification Request<a href="#handle-notification-request" class="hash-link" aria-label="Direct link to Handle Notification Request" title="Direct link to Handle Notification Request"></a></h4><ul><li><p>A <code>PushNotificationRequest</code> message MUST be wrapped in a
|
||
<a href="/status/62/payloads"><code>ApplicationMetadataMessage</code></a> with type set to <code>PUSH_NOTIFICATION_REQUEST</code>.</p></li><li><p>Where <code>message</code> is the encrypted payload of the message and
|
||
<code>chat_id</code> is the <code>SHAKE-256</code> of the <code>chat_id</code>.
|
||
<code>message_id</code> is the id of the message,
|
||
<code>author</code> is the <code>SHAKE-256</code> of the public key of the sender.</p></li><li><p>If multiple server are available for a given push notification,
|
||
only one notification MUST be sent.</p></li><li><p>If no response is received a client SHOULD wait at least 3 seconds,
|
||
after which the request MAY be retried against a different server.</p></li><li><p>This message SHOULD be sent using an ephemeral key.</p></li></ul><p>On receiving the message, the push notification server MUST validate the access token.
|
||
If the access token is valid, a notification MUST be sent to the
|
||
<a href="https://github.com/appleboy/gorush" target="_blank" rel="noopener noreferrer">gorush</a> instance with the following data:</p><div class="language-yaml codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-yaml codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"notifications"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"tokens"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"token_a"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"token_b"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"platform"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"You have a new message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"data"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"chat_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> chat_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token key atrule">"installation_ids"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">installation_id_1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> installation_id_2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p>Where platform is 1 for iOS and 2 for Firebase, according to the <a href="https://github.com/appleboy/gorush" target="_blank" rel="noopener noreferrer">gorush documentation</a>.</p><p>A server MUST return a response message:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationReport {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool success = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ErrorType error = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> enum ErrorType {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> UNKNOWN_ERROR_TYPE = 0;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> WRONG_TOKEN = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> INTERNAL_ERROR = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> NOT_REGISTERED = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes public_key = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> string installation_id = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message PushNotificationResponse {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes message_id = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated PushNotificationReport reports = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p>Where <code>message_id</code> is the <code>message_id</code> sent by the client.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="handle-notification-response">Handle Notification Response<a href="#handle-notification-response" class="hash-link" aria-label="Direct link to Handle Notification Response" title="Direct link to Handle Notification Response"></a></h4><ul><li><p>A <code>PushNotificationResponse</code> message MUST be wrapped in a
|
||
<a href="/status/62/payloads"><code>ApplicationMetadataMessage</code></a> with type set to <code>PUSH_NOTIFICATION_RESPONSE</code>.</p></li><li><p>The response MUST be sent on the
|
||
<a href="/waku/standards/application/54/x3dh-sessions">partitioned topic</a>
|
||
of the sender and
|
||
MUST not be encrypted using the
|
||
<a href="/waku/standards/application/53/x3dh">secure transport</a>
|
||
to facilitate the usage of ephemeral keys.</p></li><li><p>If the request is accepted <code>success</code> MUST be set to <code>true</code>.
|
||
Otherwise <code>success</code> MUST be set to <code>false</code>.</p></li><li><p>If <code>error</code> is <code>BAD_TOKEN</code> the client MAY query again the server for the token and
|
||
retry the request.</p></li><li><p>If <code>error</code> is <code>INTERNAL_ERROR</code> the client MAY retry the request.</p></li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="protobuf-description">Protobuf Description<a href="#protobuf-description" class="hash-link" aria-label="Direct link to Protobuf Description" title="Direct link to Protobuf Description"></a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationregistration">PushNotificationRegistration<a href="#pushnotificationregistration" class="hash-link" aria-label="Direct link to PushNotificationRegistration" title="Direct link to PushNotificationRegistration"></a></h4><p><code>token_type</code>: the type of token. Currently supported is <code>APN_TOKEN</code> for Apple Push.</p><p><code>device_token</code>: the actual push notification token sent by <code>Firebase</code> or
|
||
<code>APN</code> and <code>FIREBASE_TOKEN</code> for firebase.</p><p><code>installation_id</code>: the <code>installation_id</code> of the device.</p><p><code>access_token</code>: the access token that will be given to clients to send push notifications.</p><p><code>enabled</code>: whether the device wants to be sent push notifications.</p><p><code>version</code>: a monotonically increasing number identifying the current <code>PushNotificationRegistration</code>.
|
||
Any time anything is changed in the record it MUST be increased by the client,
|
||
otherwise the request will not be accepted.</p><p><code>allowed_key_list</code>: a list of <code>access_token</code> encrypted with the AES key
|
||
generated by Diffie–Hellman between the publisher and the allowed contact.</p><p><code>blocked_chat_list</code>: a list of <code>SHA2-256</code> hashes of chat ids.
|
||
Any chat id in this list will not trigger a notification.</p><p><code>unregister</code>: whether the account should be unregistered.</p><p><code>grant</code>: the grant for this specific server.</p><p><code>allow_from_contacts_only</code>: whether the client only wants
|
||
push notifications from contacts.</p><p><code>apn_topic</code>: the APN topic for the push notification.</p><p><code>block_mentions</code>: whether the client does not want to be notified on mentions.</p><p><code>allowed_mentions_chat_list</code>: a list of SHA2-256 hashes of chat ids
|
||
where we want to receive mentions.</p><p>DATA DISCLOSED</p><ul><li><p>Type of device owned by a given user.</p></li><li><p>The <code>FIREBASE</code> or <code>APN</code> push notification token,</p></li><li><p>Hash of the <code>chat_id</code> a user is not interested in for notifications,</p></li><li><p>The number of times a push notification record has been modified by the user,</p></li><li><p>The number of contacts a client has, in case <code>allowed_key_list</code> is set.</p></li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationregistrationresponse">PushNotificationRegistrationResponse<a href="#pushnotificationregistrationresponse" class="hash-link" aria-label="Direct link to PushNotificationRegistrationResponse" title="Direct link to PushNotificationRegistrationResponse"></a></h4><p><code>success</code>: whether the registration was successful</p><p><code>error</code>: the error type, if any</p><p><code>request_id</code>: the <code>SHAKE-256</code> hash of the <code>signature</code> of the request</p><p><code>preferences</code>: the server stored preferences in case of an error</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="contactcodeadvertisement">ContactCodeAdvertisement<a href="#contactcodeadvertisement" class="hash-link" aria-label="Direct link to ContactCodeAdvertisement" title="Direct link to ContactCodeAdvertisement"></a></h4><p><code>push_notification_info</code>: the information for each device advertised</p><p>DATA DISCLOSED</p><ul><li>The chat key of the sender</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationquery">PushNotificationQuery<a href="#pushnotificationquery" class="hash-link" aria-label="Direct link to PushNotificationQuery" title="Direct link to PushNotificationQuery"></a></h4><p><code>public_keys</code>: the <code>SHAKE-256</code> of the public keys the client is interested in</p><p>DATA DISCLOSED</p><ul><li>The hash of the public keys the client is interested in</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationqueryinfo">PushNotificationQueryInfo<a href="#pushnotificationqueryinfo" class="hash-link" aria-label="Direct link to PushNotificationQueryInfo" title="Direct link to PushNotificationQueryInfo"></a></h4><p><code>access_token</code>: the access token used to send a push notification</p><p><code>installation_id</code>: the <code>installation_id</code> of the device associated with the <code>access_token</code>.</p><p><code>public_key</code>: the <code>SHAKE-256</code> of the public key associated with this <code>access_token</code>
|
||
and <code>installation_id</code>.</p><p><code>allowed_key_list</code>: a list of encrypted access tokens to be returned
|
||
to the client in case there’s any filtering on public keys in place.</p><p><code>grant</code>: the grant used to register with this server.</p><p><code>version</code>: the version of the registration on the server.</p><p><code>server_public_key</code>: the compressed public key of the server.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationqueryresponse">PushNotificationQueryResponse<a href="#pushnotificationqueryresponse" class="hash-link" aria-label="Direct link to PushNotificationQueryResponse" title="Direct link to PushNotificationQueryResponse"></a></h4><p><code>info</code>: a list of <code>PushNotificationQueryInfo</code>.</p><p><code>message_id</code>: the message id of the <code>PushNotificationQueryInfo</code>
|
||
the server is replying to.</p><p><code>success</code>: whether the query was successful.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotification">PushNotification<a href="#pushnotification" class="hash-link" aria-label="Direct link to PushNotification" title="Direct link to PushNotification"></a></h4><p><code>access_token</code>: the access token used to send a push notification.
|
||
<code>chat_id</code>: the <code>SHAKE-256</code> of the <code>chat_id</code>.
|
||
<code>public_key</code>: the <code>SHAKE-256</code> of the compressed public key of the receiving client.
|
||
<code>installation_id</code>: the <code>installation_id</code> of the receiving client.
|
||
<code>message</code>: the encrypted message that is being notified on.
|
||
<code>type</code>: the type of the push notification, either <code>MESSAGE</code> or <code>MENTION</code>
|
||
<code>author</code>: the <code>SHAKE-256</code> of the public key of the sender</p><p>Data disclosed</p><ul><li><p>The <code>SHAKE-256</code> hash of the <code>chat_id</code> the notification is to be sent for</p></li><li><p>The cypher text of the message</p></li><li><p>The <code>SHAKE-256</code> hash of the public key of the sender</p></li><li><p>The type of notification</p></li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationrequest">PushNotificationRequest<a href="#pushnotificationrequest" class="hash-link" aria-label="Direct link to PushNotificationRequest" title="Direct link to PushNotificationRequest"></a></h4><p><code>requests</code>: a list of PushNotification
|
||
<code>message_id</code>: the <a href="/status/62/payloads">Status message id</a></p><p>Data disclosed</p><ul><li>The status <code>message_id</code> for which the notification is for</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationresponse">PushNotificationResponse<a href="#pushnotificationresponse" class="hash-link" aria-label="Direct link to PushNotificationResponse" title="Direct link to PushNotificationResponse"></a></h4><p><code>message_id</code>: the <code>message_id</code> being notified on.
|
||
<code>reports</code>: a list of <code>PushNotificationReport</code></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="pushnotificationreport">PushNotificationReport<a href="#pushnotificationreport" class="hash-link" aria-label="Direct link to PushNotificationReport" title="Direct link to PushNotificationReport"></a></h4><p><code>success</code>: whether the push notification was successful.
|
||
<code>error</code>: the type of the error in case of failure.
|
||
<code>public_key</code>: the public key of the user being notified.
|
||
<code>installation_id</code>: the <code>installation_id</code> of the user being notified.</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="anonymous-mode">Anonymous Mode<a href="#anonymous-mode" class="hash-link" aria-label="Direct link to Anonymous Mode" title="Direct link to Anonymous Mode"></a></h3><p>In order to preserve privacy, the client MAY provide anonymous mode of operations
|
||
to propagate information about the user.
|
||
A client in anonymous mode can register with the server
|
||
using a key that is different from their chat key.
|
||
This will hide their real chat key. This public key is effectively a secret and
|
||
SHOULD only be disclosed to clients approved to notify a user.</p><ul><li><p>A client MAY advertise the access token on the
|
||
<a href="/waku/standards/application/53/x3dh">contact-code topic</a>
|
||
of the key generated.</p></li><li><p>A client MAY share their public key contact updates in the
|
||
<a href="https://developers.google.com/protocol-buffers/" target="_blank" rel="noopener noreferrer">protobuf record</a>.</p></li><li><p>A client receiving a push notification public key
|
||
SHOULD listen to the contact code topic of the push notification public key for updates.</p></li></ul><p>The method described above effectively does not share the identity of the sender
|
||
nor the receiver to the server, but
|
||
MAY result in missing push notifications
|
||
as the propagation of the secret is left to the client.
|
||
This can be mitigated by <a href="/status/62/payloads">device syncing</a>,
|
||
but not completely addressed.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="securityprivacy-considerations">Security/Privacy Considerations<a href="#securityprivacy-considerations" class="hash-link" aria-label="Direct link to Security/Privacy Considerations" title="Direct link to Security/Privacy Considerations"></a></h2><p>If anonymous mode is not used,
|
||
when registering with a push notification service a client will disclose:</p><ul><li><p>The devices that will receive notifications.</p></li><li><p>The chat key.</p></li></ul><p>A client MAY disclose:</p><ul><li>The hash of the <code>chat_id</code> they want to filter out.</li></ul><p>When running in anonymous mode, the client’s chat key is not disclosed.</p><p>When querying a push notification server a client will disclose:</p><ul><li>That it is interested in sending push notification to another client,
|
||
but querying client’s chat key is not disclosed.</li></ul><p>When sending a push notification a client will disclose:</p><ul><li>The <code>shake-256</code> of the <code>chat_id</code>.</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="copyright">Copyright<a href="#copyright" class="hash-link" aria-label="Direct link to Copyright" title="Direct link to Copyright"></a></h2><p>Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/" target="_blank" rel="noopener noreferrer">CC0</a>.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="references">References<a href="#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References"></a></h2><ol><li><a href="https://github.com/status-im/specs/blob/master/docs/raw/push-notification-server.md" target="_blank" rel="noopener noreferrer">PUSH-NOTIFICATION-SERVER, Initial Specification</a></li><li><a href="https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1" target="_blank" rel="noopener noreferrer">Push Notification, Apple Developer</a></li><li><a href="https://firebase.google.com" target="_blank" rel="noopener noreferrer">Firebase</a></li><li><a href="/waku/standards/core/13/store">13/WAKU2-STORE</a></li><li><a href="https://github.com/appleboy/gorush" target="_blank" rel="noopener noreferrer">gorush</a></li><li><a href="/waku/standards/application/54/x3dh-sessions">54/WAKU2-X3DH-SESSIONS</a></li><li><a href="/status/62/payloads">62/PAYLOAD</a></li><li><a href="https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf" target="_blank" rel="noopener noreferrer">SHAKE-256</a></li><li><a href="https://developers.google.com/protocol-buffers" target="_blank" rel="noopener noreferrer">Protocol Buffers</a></li><li><a href="/waku/standards/application/53/x3dh">53/WAKU2-X3DH</a></li></ol></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/status/65/account-address"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M11.667 6.417h-7.1l3.261-3.261L7 2.333 2.333 7 7 11.667l.823-.823-3.255-3.26h7.099V6.417Z" fill="#fff"></path></svg></div><span class="lsd-typography lsd-typography--body2 pagination-nav__label">65/STATUS-ACCOUNT-ADDRESS</span></a></nav></div></div><div class="gap1_XuuQ"></div><div class="toc_pP_5"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#abstract" class="table-of-contents__link toc-highlight">Abstract</a></li><li><a href="#background" class="table-of-contents__link toc-highlight">Background</a></li><li><a href="#specification" class="table-of-contents__link toc-highlight">Specification</a><ul><li><a href="#definitions" class="table-of-contents__link toc-highlight">Definitions</a></li><li><a href="#server-components" class="table-of-contents__link toc-highlight">Server Components</a></li><li><a href="#requirements" class="table-of-contents__link toc-highlight">Requirements</a></li><li><a href="#push-notification-server-flow" class="table-of-contents__link toc-highlight">Push Notification Server Flow</a></li><li><a href="#registering-client" class="table-of-contents__link toc-highlight">Registering Client</a></li></ul></li><li><a href="#push-notification-server" class="table-of-contents__link toc-highlight">Push Notification Server</a><ul><li><a href="#query-topic" class="table-of-contents__link toc-highlight">Query Topic</a></li><li><a href="#sending-client" class="table-of-contents__link toc-highlight">Sending Client</a></li><li><a href="#protobuf-description" class="table-of-contents__link toc-highlight">Protobuf Description</a></li><li><a href="#anonymous-mode" class="table-of-contents__link toc-highlight">Anonymous Mode</a></li></ul></li><li><a href="#securityprivacy-considerations" class="table-of-contents__link toc-highlight">Security/Privacy Considerations</a></li><li><a href="#copyright" class="table-of-contents__link toc-highlight">Copyright</a></li><li><a href="#references" class="table-of-contents__link toc-highlight">References</a></li></ul></div></div></div></div></main></div></div><footer class="footer"><div class="container container-fluid firstRow_ar1q"><div class="footer__bottom text--center"><div class="margin-bottom--sm"><a class="footerLogoLink_BH7S" href="/"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--light_BL8e footer__logo" width="22"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--dark_OvIx footer__logo" width="22"></a></div><div class="footer__copyright">Vac @2025<br>All Rights Reserved.</div></div><div class="row footer__links"><div class="col footer__col"><div class="footer__title"></div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://x.com/vacp2p" target="_blank" rel="noopener noreferrer" class="footer__link-item">Twitter<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://discord.gg/PQFdubGt6d" target="_blank" rel="noopener noreferrer" class="footer__link-item">Discord<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://github.com/vacp2p" target="_blank" rel="noopener noreferrer" class="footer__link-item">Github<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title"></div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://jobs.status.im/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Work with us<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a class="footer__link-item" href="/terms">Terms & conditions</a></li><li class="footer__item"><a class="footer__link-item" href="/privacy-policy">Privacy Policy</a></li><li class="footer__item"><a class="footer__link-item" href="/security">Security</a></li></ul></div></div></div><div class="secondRow__ww3"><span class="footer__bottom text--center">Built by <a href="https://free.technology/" target="_blank" class="footerLink_sh7M">IFT</a></span><div class="row footer__links"><div class="col footer__col"><div class="footer__title">Research</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://vac.dev" target="_blank" rel="noopener noreferrer" class="footer__link-item">VacP2P<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://afaik.institute" target="_blank" rel="noopener noreferrer" class="footer__link-item">AFAIK<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">Infrastructure</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://waku.org/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Waku<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://nimbus.team/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Nimbus<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://codex.storage" target="_blank" rel="noopener noreferrer" class="footer__link-item">Codex<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://nomos.tech" target="_blank" rel="noopener noreferrer" class="footer__link-item">Nomos<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">Creative Studio</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://acid.info" target="_blank" rel="noopener noreferrer" class="footer__link-item">Acid.info<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">Movement</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://logos.co" target="_blank" rel="noopener noreferrer" class="footer__link-item">Logos<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">User-facing products</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://status.im" target="_blank" rel="noopener noreferrer" class="footer__link-item">Status<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://keycard.tech" target="_blank" rel="noopener noreferrer" class="footer__link-item">Keycard<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div></div></div><button class="backToTop_wDfN lsd-button lsd-button--small lsd-button--outlined"><span class="lsd-typography lsd-typography--label2 lsd-button__text">Back to top ↑</span></button></footer></div></div>
|
||
<script src="/assets/js/runtime~main.db01e95f.js"></script>
|
||
<script src="/assets/js/main.7bd63d25.js"></script>
|
||
</body>
|
||
</html> |