diff --git a/client/components/Editor/schemas/base.ts b/client/components/Editor/schemas/base.ts index 40cc241096..71896de375 100644 --- a/client/components/Editor/schemas/base.ts +++ b/client/components/Editor/schemas/base.ts @@ -268,15 +268,22 @@ export const baseMarks = { }, ], toDOM: (node) => { - /* Links seem to be recieving a target attr that is a dom element */ + /* Links seem to be receiving a target attr that is a dom element */ /* coming from the wrong source in some interfaces. This ensures */ /* only strings can be a target attr. */ - const attrs = node.attrs; + const attrs = { ...node.attrs }; if (attrs.target && typeof attrs.target !== 'string') { attrs.target = null; } + const { pubEdgeId, ...restAttrs } = attrs; - return ['a', { 'data-pub-edge-id': pubEdgeId, ...restAttrs }] as DOMOutputSpec; + return [ + 'a', + { + 'data-pub-edge-id': pubEdgeId, + ...restAttrs, + }, + ] as DOMOutputSpec; }, }, sub: { diff --git a/client/containers/Pub/PubDocument/PubDiscussions/Discussion/DiscussionInput.tsx b/client/containers/Pub/PubDocument/PubDiscussions/Discussion/DiscussionInput.tsx index 99623486f3..e8ee6874ba 100644 --- a/client/containers/Pub/PubDocument/PubDiscussions/Discussion/DiscussionInput.tsx +++ b/client/containers/Pub/PubDocument/PubDiscussions/Discussion/DiscussionInput.tsx @@ -18,6 +18,8 @@ import { buttons, FormattingBar } from 'components/FormattingBar'; import { usePubContext } from 'containers/Pub/pubHooks'; import { usePageContext } from 'utils/hooks'; +import { commentEditorCustomMarks } from './commentEditorMarks'; + type OwnProps = { discussionData: any; isPubBottomInput?: boolean; @@ -237,6 +239,7 @@ const DiscussionInput = (props: Props) => { { setChangeObject(editorChangeObject); }} diff --git a/client/containers/Pub/PubDocument/PubDiscussions/Discussion/ThreadComment.tsx b/client/containers/Pub/PubDocument/PubDiscussions/Discussion/ThreadComment.tsx index ac3f9ef8fe..50c3fb735c 100644 --- a/client/containers/Pub/PubDocument/PubDiscussions/Discussion/ThreadComment.tsx +++ b/client/containers/Pub/PubDocument/PubDiscussions/Discussion/ThreadComment.tsx @@ -20,6 +20,8 @@ import { buttons, FormattingBar } from 'components/FormattingBar'; import { usePageContext } from 'utils/hooks'; import { getPartsOfFullName } from 'utils/names'; +import { commentEditorCustomMarks } from './commentEditorMarks'; + import './threadComment.scss'; import type { CommunityBan } from 'server/models'; @@ -185,6 +187,7 @@ const ThreadComment = (props: Props) => { key={key} isReadOnly={isReadOnly} initialContent={threadCommentData.content} + customMarks={commentEditorCustomMarks} onChange={onChange} /> ); diff --git a/client/containers/Pub/PubDocument/PubDiscussions/Discussion/commentEditorMarks.ts b/client/containers/Pub/PubDocument/PubDiscussions/Discussion/commentEditorMarks.ts new file mode 100644 index 0000000000..d9d05b9e51 --- /dev/null +++ b/client/containers/Pub/PubDocument/PubDiscussions/Discussion/commentEditorMarks.ts @@ -0,0 +1,31 @@ +import type { DOMOutputSpec, MarkSpec } from 'prosemirror-model'; + +import { baseMarks } from 'components/Editor/schemas/base'; + +// this just adds a rel=nofollow to the link +const commentLinkMark: MarkSpec = { + ...baseMarks.link, + toDOM: (node) => { + const attrs = { ...node.attrs }; + const hasInvalidTarget = attrs.target && typeof attrs.target !== 'string'; + + if (hasInvalidTarget) { + attrs.target = null; + } + + const { pubEdgeId, ...restAttrs } = attrs; + + return [ + 'a', + { + 'data-pub-edge-id': pubEdgeId, + ...restAttrs, + rel: 'nofollow', + }, + ] as DOMOutputSpec; + }, +}; + +export const commentEditorCustomMarks = { + link: commentLinkMark, +}; diff --git a/infra/.env.dev.enc b/infra/.env.dev.enc index 6abec74ccc..4634728ccb 100644 --- a/infra/.env.dev.enc +++ b/infra/.env.dev.enc @@ -1,53 +1,54 @@ -AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:2n/7JK6hVcQcfKIW4OL+kOx7RfDznjKrtUl2VxL3NbJf1QN/eItuVfM3qhPbYSrY/D1kHIsyFaqCSHUAXCYMow==,iv:d/CUqge7Ij3p7HWPpLfP7mP/QqGI4I1Yr0lPs7SrUxY=,tag:Mg8CCaBgfa9/u9kj45LRfg==,type:str] -ALGOLIA_ID=ENC[AES256_GCM,data:mVQhuuBZIDOAbg==,iv:0TpziBJfONr6zbT15zSe0Zo5M3KijF86/JIijigQ9z8=,tag:Aa+Ep1sY8JGj4JjMbCeWGw==,type:str] -ALGOLIA_KEY=ENC[AES256_GCM,data:9a04uCh1RDiLKLsQAD1nfera+9F8pzMnjT1XoVgwO8o=,iv:O2Pyp0c7sUAlHNjrbusHeradBD6nrATRuJuSSoV/TEM=,tag:cgEdk/iIaSv/7v+JNdlBzg==,type:str] -ALGOLIA_SEARCH_KEY=ENC[AES256_GCM,data:XFEHaETJnQBUS6AU2eD1xLvbR3KznBqbVuzmekPXIeY=,iv:KfnSxj+gTLYaNDH6O/3/UBRLpyBnJqK2kFrLZU3BVRE=,tag:XciICCsvXkOVfnnr63+qvQ==,type:str] -ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:ZDHT977QVa6YwfruNJNXNrq//yPKauYmp8FuGsqAwIPjNunI+cJwDvH1ZtGRsTh6QBYluEMnkIuMQg8sltwstHKFYNsqfaTbKLaR858F9vS7+SeLDoY1T7j+tyjDJb4H6iulifbWkB6SvnhJ+FRISzFIS1AYhKdVgr5avMsrZEg=,iv:cOOS1w6Ka1lgYnTx03kYT2LTcR4kSh62MZF9Y1w9WDA=,tag:Md/D8quVVrEJ4gfOib67zA==,type:str] -AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:FkmjWki3JfPoRz/Sh/Pfcw+ZPUs=,iv:14hC2HKCsbW9QwR5z8ZYLc92nFrHbF5vygVIyLBrKP0=,tag:Q0GGXfNep1zv3AlRFaHnZA==,type:str] -AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:EcKDTCdBgRV5qH5GfYtYloUP1+Q=,iv:MbCQNcueEzw12Q/mGm9yk6kLtvCY9FFoMI+9qOCc1s0=,tag:Ni2kBLR03ziuu3ILjJlcnQ==,type:str] -AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:sRi+exMVDEmSmXobGG8yqRbp0fDS5k6JR2VoWDCcRuESo9AhQeS5/g==,iv:X0wAYyeGZgltCPqv18+jg7+hGbK8tRrUWPd22YJUmfY=,tag:51Y9KgErzcD8WqdR3OfhBg==,type:str] -AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:EXWEN0SfEl1UTy0gWsc0Jg4nhZxh/cQaI2IuoqUGP61psXkDi2IPZw==,iv:fmT1GiiqnUtTyHWDlOMGKk81cPHYptX3uP957UL71C0=,tag:xWuEh16BHIaDLWQuAHQiug==,type:str] -BACKUPS_SECRET=ENC[AES256_GCM,data:4dv5DWGoNdQxx8Vody4V8Zs1UhWudyE0xlPy0LG21NalH4xGofEjknUvpiE=,iv:umZ4CkdKMygeo5Rj2zDuhOFJbr2k99IDlU5bfjCgKTw=,tag:m5YT/weKGfzve1m+/n0zsQ==,type:str] -DATABASE_URL=ENC[AES256_GCM,data:72ZoQXJ5gKxFxqp9bcPvF/WC8661hcfigxHpHDJ22fWR3K2m8wkheYPv6VQ=,iv:xHCcYJ7KhTPM8VDPzS76gCVIxgSPrltKqgd4nM1L+hE=,tag:Bu1w8y9JC0Q7rBX44Bf17Q==,type:str] -DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:T6GqlTrgOXsjjx9wi7X08PtQqs1chUqgJrPkQuOAoancdA==,iv:uxU+g7LY9v5k9DNm6lC6vIuk6mqkaoDPltIqYKOB6u0=,tag:SzxE4C8OpJ1p49JEhqiJdQ==,type:str] -DOI_LOGIN_ID=ENC[AES256_GCM,data:OIZ/kApo,iv:22epUCTbQEHw6x24U2h+D/BL2V+SxpvRIY5lFsklEYE=,tag:f1eJKluloGC/brxO/c2sOg==,type:str] -DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:+YEQvn1ve+Ib0kpT4dwsY3ZuLAI=,iv:XHHilnUA63cnWIhx3pobuTnmXN4eX0jvak09rYUJHWY=,tag:hGLpjv6O5MAsS2KziWVdSg==,type:str] -DOI_SUBMISSION_URL=ENC[AES256_GCM,data:Hx5cdFHYGnpxdr6A82j3UX5TvAnWBYikqKlrWMqLTRIYHxdmZs9j1SQ=,iv:cERuN0RSY5OgtCx1Al1PY0z+VChoSCAXm+w4MWR5ov0=,tag:6jKSzNWw1mJPqTlGILLjcw==,type:str] -FASTLY_PURGE_TOKEN_DUQDUQ=ENC[AES256_GCM,data:X83GNq6ccbTlmVJSSepKFaZeqn9zxBas7d/CButEKDE=,iv:0D0zMcIuhwMho1UHwR17Vw4+4+rojNMA+Hjj3kQhB5k=,tag:8Zl2RXzBn6YLbmQant/bWg==,type:str] -FASTLY_SERVICE_ID_DUQDUQ=ENC[AES256_GCM,data:g/9urOSjcltTP0/1LJF6IY4ZA+IKaA==,iv:nmO4R+VIvR+JLqtqFSjw8pCxIjJpAqN5K0iQCoI7fvc=,tag:6VjnieND5Ro/kU8MhWcrZQ==,type:str] -FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data: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,iv:6TABp3Yk0yuhuvzOe8zjLiArHjZC7K1l9lRIJBV7CVw=,tag:oIJ2LIiYHCjdt+qZL3DAtA==,type:str] -IS_DUQDUQ=ENC[AES256_GCM,data:BdBWyg==,iv:zES5Cnz2uWWfcLHkzACNwL+8eJYfbP7aehWfEb4KkpY=,tag:yE4CJNW2aZgxuIm2mqsvPQ==,type:str] -JWT_SIGNING_SECRET=ENC[AES256_GCM,data:EI6vLbJwz7xjzbvQtegXBQIonxCevlYuiJPDZh2sstrUY57DKJTtCOSb67ZTCJbwBcnFwkgBJ7VpIZxt+oXdq2DgwWSaP+HS5jrmQ6L9rRvQveFrHD9sPBr2b/WrmiHrQYAUbBdw8OntlDCh8tP7O/f44nCcYxFYtZMsPjkGn8U3Zd8tOYQOXX/esiANPd1mXMwg5aibY6WRZkPugT5SzMp3YUxOb9u8AhX3YmTlcNr1bG+rO9UR1SmynZNd3t4UxyVcLQgR7TRf7r/qyLKv01Hl86CyEcIO9yF0bH7AMjo+Bxc5idlYqpT1zinfuGv/DLRu9dWa2n1/lKxRobYGACmiPzu5gHA1Ga9kKXDsP8Mo3LEc3i03yM8YeRv6cZCztCfb4+5dOa9buYB+BcomqX7xRyZHYcPRIT0wXRKQZ1VgdZApnOwwX0K0SDmPLojn54eGyfl+QhcDYZE+m9ZuMlnXXv15UGWdg5KLdEqRyoBRFc0QjfBWDiNMxDvAzEAq6UchRTYtncySP33ArTFGJ3/GaMfiZgXRN04sRBc6sF/f1OLBVJW7/UHDuUQAJqU9+tA3l7K/ZUX9eQDGlCJBOu+7GuKcB6bZAIYD1oZryMk03REYQ2G2pST7oZx50cnFIKxFstSOso7evs8EGMtUBXTUV9Z0ML55sgixpwwDgkCOF8qpzEph+KgCUeIgMTfJpZ3lf9hic1yAPzGJwpWQWxlGq92/HPi9rzDChdhazyM65GvnQb1Xs7tPPVuoLie0SUr8cPp/bkcvRf1GeEu7g3991AFrr/+psdGxep3gi4ZA7VN+CJoOmWplH5z8KHezwcJy9KWpUECkRmGuWX3FzBoLSJE9RusD1yzqXyREArFlcKkQefRfzrJSmw2mbYbUm/YdOxiMw2/z0PxIA5B0mTRTQlSEUrgsJ4LDCI1PNZAy+Y1E1vNSunYmPdaTN78ArkeVNwUtPwU1oaqgRMRq1jR7GVS+aZ7WSdGjE2ecejncGlGvVQWXxPWYkZw8USWn7wWFaBLb0nBfRdeRYSYHGMd+ykFthSpg4IfVeFbxFGZwa1ZYyuPhrhDaIOxD1IPe3dUeAS4Fj8xkBVoWfZnKFthsb7yfC1ZVQhmjXNUFpD/BotpAV0l7IEJ/4mTE6BSUI1x+Lj0EnPvfPCWdOlxlQ05QdkvpmzghiMycZ0LpTt0ac32vR0Nllidlb3Bq4GDSDgdEnAA/wnNk2JrU+yr+xLUQ13OiGq6E3/aJSiHCEHXA/XeTUTkoGUfBDzrNUCHk1EgCGeoLk5M6hTgil1IajlFLDLTu754/pReds4etWiM3p4eoDkTsKvAQq34/sUJzpEHarLRxgVi4SbP7wCdm9A==,iv:/5b2uU4wtSW6MxHZT+qOvcET6XC+irrKF2yLqGnFYNc=,tag:6KUtS2orURTBaHxz4sTSeQ==,type:str] -MAILCHIMP_API_KEY=ENC[AES256_GCM,data:95/pAWPhlf9hgAu22YC5BnNlPEKZpcZBoEu/cKZiHPVll6LI,iv:enxUGoEVtPnNdjdk1/WrYjKH34Nk8JZaj8uUwizSGAo=,tag:sseB7726W3t/IUoJH77BPQ==,type:str] -MAILGUN_API_KEY=ENC[AES256_GCM,data:w6yEapPJnye7ZO2LcB4N/BxfTv37Fz4fH3Q4jIjrgqUCHBZe,iv:31e7anTZSPwR02JZCDZ0rZqGobsFVp85NOmzTagHgPQ=,tag:fIpN1F7BkEQtsm5WiB+7Xg==,type:str] -METABASE_SECRET_KEY=ENC[AES256_GCM,data:AwPoz6nJwPuOMMopQFtCletph4iQMIAViga9cBlwy4Vg111ppAMltSaaFrBCcyoekb1PEtIxWoNmQm6Eg8tRkg==,iv:wbVYkFgAjtvl5s+T07WMUW7Zm2G3CHxAv55jwXVDTGc=,tag:Y8OtdcaGw/fhjeE+yRYtTw==,type:str] -NODE_ENV=ENC[AES256_GCM,data:GCzZEgN/I4kTKw==,iv:RnqYh5w2Q1M7MaHdfkS3Paq3O/S570ZR3Nb0gbf6nkk=,tag:Yrihp3nCdm8Dng9WTJkKuw==,type:str] -PUBSTASH_ACCESS_KEY=ENC[AES256_GCM,data:qBxb/l0=,iv:MQBdvvmcPKbPbfgXnSUpTyVlbFeTrAYFgWHU4HjKq6E=,tag:LcegYEQd0hX9TVkcGCjCtA==,type:str] -PUBSTASH_URL=ENC[AES256_GCM,data:l6guNKVCvM6ZYdLjbozpdu9wMx1xItxx,iv:Hx+TMeSaUmZlzOR+NcTlce6+IfyYlldR+/CpE6MpwDk=,tag:7XpDMya25d/8f+vkv/7yDw==,type:str] -S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:TEDtO1OArx6f78FFj5du4NBMreIQujd6gVMSdVAAmJKDuF0=,iv:hBSYHXoi62y80v1Y3auT1v9paq54XVUxrylNibWAfe8=,tag:C59ElGe0hv3VZCUKkpeQdQ==,type:str] -S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:01J1yRDYxvPa7IVoezrI7ayMypU=,iv:YLrY08CNWC3xfb/4IA/eyi4CVYFA2ku5YwoRIPnXIcs=,tag:uzG3DI/GhppuGJhMTbELgQ==,type:str] -S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:52/kMIkDQ46Z7QU1V+gH0LuH7/p+qf26Z3z+spMEK5z0VvBC/unZPA==,iv:O15uLKzHtEP9wxBgZWxFQB+wgqMHSj4znvbYdXe+fPE=,tag:RIbBA36e48wgZqjWKfxtew==,type:str] -S3_BACKUP_BUCKET=ENC[AES256_GCM,data:3gDOAFTDYGZ4Su0=,iv:fF+xxCSbbAcDGZkFCvtNPqfjV5KqR6vERl2DSRQ6n9c=,tag:W/ZM76ZY87bapsuJ3H2CQw==,type:str] -SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:H4zK4Yp4FxD1Ny2fIwukSGjrnpigzi1xHP96OIwX088ERRqJCzQpefj9F5KE+ohyi1Ngm7u3jIsf1D+Iggz1FSbTRIQtSLIqdDpjtwPgboCTdva8bxQwpfmhTN/AWVJsDD8Zlx7Uh5ccm6NEaeAkOusMyio6rgUyRjFv81UaZ6BjfU0LaVWwWUssmGhoeYG3ktTC49V2l83iRPZeynjooiT8FkP/4tmR9FzTXD94FuuVsq5CC3MASKpPlA==,iv:9uLqugx5gaW6hd5T8UE833/5kv590NDmDTdiSh9oNDc=,tag:Lc0KqU+JraOom7zCBDzGfA==,type:str] -SENTRY_ORG=ENC[AES256_GCM,data:lDDe,iv:LC/DAwa15cA094yHoG8Xr5dBsP4N5vl2ZMAfU4cHjFs=,tag:uAJo7GuLG9lKZQK8qDXVlA==,type:str] -SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:Zo8=,iv:oK4AUeGNyBGfYHNCkkeVhs7bAIksTUsBJ/6BaBvISfM=,tag:Std2RUhC+F7Xk1TDt+2Y3A==,type:str] -SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:pi4VFuXjO7VrlKQ0uNCCrIxyVOXfmIM3UxWzqQGyiPZscsCE/wq/h9nbvZ7oPWzfuFxdyvIrRkB6nCYkvoCLjQF8cNabWieI11ZnuA1LIQ==,iv:PccN6ZFsITrCR5fuqRThJKZa3SSXhSe3dOgQ2UvqKf0=,tag:EdrTdLqXrw0BicoM+wuQ7w==,type:str] -STITCH_WEBHOOK_URL=ENC[AES256_GCM,data:9g6i80PoR5VDf/be+7QetlvrvWZnYx/X6fXvsIMFdvNytKWkSw0Anvdv1XVkABlInSiiWcDdljT6eXGy1xaHWlDNPV93VVXj0ilAaFp+HTesjkJvuxcgGCGmqt1WfdFBJvR1CqZAK0+CtRsN4LFRx3rqfyVS,iv:3vQ+MB+1ZOHhgOn0Qk+qmUl1QE89E4hqII/uCaEuZVA=,tag:vA/h/ruvZE1YZtLa6m/VLA==,type:str] -ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:rk5PkeblJ/hOeH3iDrMbdGACKGU=,iv:8rxaC+oIIx9YzdW/AMzOgU0tzciixdMrAgYYTTgb1T8=,tag:AvhhoW1rRvd4KYt0wsfX7g==,type:str] -ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:IIefJtRuBIALjageUdGLtwA3daw=,iv:ZVmwdqgYZCD6y+O10K5GmyTKJtNnIArnVxADSRHwbNA=,tag:DHP2Dw/l+Wf2vw8oHjMi7w==,type:str] -sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByQWF4M09QcXhjZGNwSGpz\naU15MEhsQVdmWmFWaDFkOTZycFd2OTExVEQwCnJ3R3h1MThjNWlkK1BGQjN0cm9z\nd2h2UEtiNGliOWJ1aHd4OGlUOE10NEEKLS0tIFZuZ1p1WSs0ZWRCTUMrNGhkdmMx\nelluaEhBME03aW9uVHdjUTFERDBiQ1EKOF3R1fXoWJoUxiiYWvIxQ8hgQ5ZBKfIT\nOHOKl0TYOjub4IxNSm6jpeyeckGQKVknToX+qfXA1sfNk+KqF/As9Q==\n-----END AGE ENCRYPTED FILE-----\n +AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:mSkzNRIjvI+c4CSL9YqE/pzGDbhZW9UgvKIt39tTMahG1DRWgyXfRnbgwsNeSUz9ENT/8+ZPo/f80qHijyDncA==,iv:b1ElzhpFtjT1GNjPDu2QTD5u2WNz6kfcdwSpaXd9zsI=,tag:u13fmVyfiBH1bKm1SPhaWA==,type:str] +ALGOLIA_ID=ENC[AES256_GCM,data:+CCJAAS2RL6ayA==,iv:uBr9MGfVdsLWe+LStVuOQb4ntmMr+WpNrdJMxKARb30=,tag:RznzIJiReu9A9B2bXL+xlQ==,type:str] +ALGOLIA_KEY=ENC[AES256_GCM,data:dqzRBiYu/KCGNwh8vn0k7KCmp8bcWTX3Qnm2Vl9fXqA=,iv:OcGoVEb6HDkpPhrz00V9pBpFxDe6sVURiyZ8IhLiwRE=,tag:9v/1nNWzrv8zsVpDRAbkoA==,type:str] +ALGOLIA_SEARCH_KEY=ENC[AES256_GCM,data:lzVljp0AxaxsXlz7zk+i6FIrqggAdJBJ37lAWmPs758=,iv:iu0s7yi34Cr5Xck1jcxrpeLEt6P1EF3RlR1DN4pkO/4=,tag:zEXiZfS7N91eaMbpDwP/7g==,type:str] +ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:sPTGbHcTcmMipmtw8i6LNekBzTMgbTHLGffCJobA1fCYaWBv8iAKiYZmrzCxaMjfaLGaHuevFfIXpnRcdPQXTOq0DTOF4ICIoaDHhdjVH16W1iJidrMPGY5B2c1n4AL/BheRs797Z9Yw/BqZdsMPXrdP/yW6EiQZ3o3n/2roRyI=,iv:NCedID8ywnz0FYZlwM/tpxWxIBpXgn/PWMgHjWJS29o=,tag:pObUaf2RZIt9gEovhXsIeQ==,type:str] +AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:pkH4bPZb5BNYySAL1ISRNhdw5fI=,iv:vqBSk563RP13fQvxvF1WRaJPtoshlVtog1aygy29ZH0=,tag:MQgLEArjcPmWJHUgLlXl1g==,type:str] +AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:Kfoa70EzKsTLHtcmK6QtFeEg6cY=,iv:uMFlYV3Zm/y3tzQjaBJCtWOWRjbw5kp0tL/t361u5G8=,tag:uMHT9xLeeUH8ynfbjMmF8w==,type:str] +AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:PelvVVT+6wo3u+N2pjqrS8dSU5cli5vgsGKO1C5Ovc0h5ji/z4huow==,iv:qsj1oXLxTz37gHSX67F8mhWTSiqVDr3wa0va+l6REK8=,tag:GxOLtqvZ2NbTOzjOb8ZDFQ==,type:str] +AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:UnOQRl0N7vDR6CpZDjZNado8SHJVMq2hZCY4p1+fe1IZqR0WCo/dPA==,iv:cGpUmYxgqENzpc4KgUtG3qSVKUVK/N05R6CXaVVO0t4=,tag:o9upBLy6+ALEXlQDzePBDQ==,type:str] +BACKUPS_SECRET=ENC[AES256_GCM,data:KhqpSzZA2qlnaley+V0EqJU7dHOi3B8pi5W4u32IlEuDZoT1b6OOv9Ou6h0=,iv:5Rz4qzKLBU8KLPgoV7Kkf60dNAvmEQ82ke59LGxQsxQ=,tag:UhVr12rc5+a8M5wEgGVVoQ==,type:str] +DATABASE_URL=ENC[AES256_GCM,data:4DccOAas1GohaggGaIS3u1m9u6XND1se6i0PVOGOOXOhTNAjJqjCEoPy8E8=,iv:cZ/QFfmApscrwJb9WpOgY1ckpozWtlZDm/AGRJe4dco=,tag:fKGZgFBKwS7OJt7eaZOe3Q==,type:str] +DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:Z70tjDTr1nujuDFboGI6neT0tFnJNec+umdH09Q6Yifobg==,iv:kuoZabrQG7HsNk+qt/BBtpRX6MOPIxNEiyc0ZXFgxr4=,tag:7Td5bmUfS9mWzOFJiG/A4Q==,type:str] +NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES=ENC[AES256_GCM,data:5mw=,iv:pmXQr/efALrCjuu+sAn+CvawboFjjkDtRmqTZ+CAFuA=,tag:2rkiL+OWZCJ3EmPzJnWkEw==,type:str] +DOI_LOGIN_ID=ENC[AES256_GCM,data:JC2fd2+e,iv:OpRRvob/eSM6gW0SU9cvB5CqvJJqYZUyuCcX8AD2ZOk=,tag:7BOfMPRbu+UVDFwtahGO6Q==,type:str] +DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:ZhjnZ4S8YKBkbfjqA2Okg+o3R/Q=,iv:84KKJW1c1/eN2XuM7cDhgbOIvE0ryVk6U2gtq7vl7gE=,tag:bqPROjTNpm7QUGWOcQKl+A==,type:str] +DOI_SUBMISSION_URL=ENC[AES256_GCM,data:U8VL82q0/a8t6wnJgdxaWkoTUIvnWNvNB7bJZt7hL3hPEGSFkO5PmSM=,iv:KokO2UW4GnQMSi/6pBaPORCu/XocY/XiEhKIHD7IJe8=,tag:8on6cbaIRzPCoy0r4XoRVg==,type:str] +FASTLY_PURGE_TOKEN_DUQDUQ=ENC[AES256_GCM,data:htwT7k+AL+NIUpUkm4IshRN/Ay14OBYJj/a7tcFHwoM=,iv:6/QVdGZpnXz9y1D9f281wdbVzXNTEQ66C4GF1lofP6s=,tag:gTT+4Sp9AZrQnv3Oci6SUw==,type:str] +FASTLY_SERVICE_ID_DUQDUQ=ENC[AES256_GCM,data:HOpisvxiJs/5nLdBUTRl8oSi9LTnNw==,iv:kFEFZP/J0RfJFXNLAA8gwJfd78rj/n8Rf8sPo3Ib3yU=,tag:VYvRKfS3bOQOqB4VKAaQpA==,type:str] +FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data: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,iv:zu/edFY6DgbdSkk78hK7rjYM81HcZxld1KX2IKdJVQ4=,tag:li8YtnnRhsQt3UBdW2GJVQ==,type:str] +IS_DUQDUQ=ENC[AES256_GCM,data:t+nt0w==,iv:m3AR0UCoPWE0AEQeu9rp4sBwERbhu/sXZPD7hoA5//U=,tag:GL1Brl9Iq/ptp/tLe7DFig==,type:str] +JWT_SIGNING_SECRET=ENC[AES256_GCM,data:Z0PZE4bQM7KSn18OabdRV/uU6xlvdrDCcLq1xlRiEb7KbcNyDN396NKNdIVWQ9I6FCxpE7plAJqGUbFwl9LZBYPYzvWMDXc+YfarL4vPqZ8/l/3XfJlodv6IHXPjb5y8a9c98V1hzOpkv/SieiGE86/gmY4CWR23DzSOxLjfyja/o6fEiwURkaY06hF6FjYWfqOGBng8v1VL7/lOM9WjDfBW4OGZQXOgcl7nc4geH3YvgKok6BY0vgzmkt/Nvnl/ANsx2A/mhzZAQJjjZv+jc8K1eAXSIg2Ba3IlCVI2MDe9/QgxH8Ws6ef9mH5emctZ/f04/SepsOwS7gJinZAJZvUR8Y/ZCJMxNLBWCHY1GjVEU7o6bEc8kOa3oq3w94NwxXMn6qN3yiH2h7NLMnZY3a2HqKmNMJu5lY/zqDxvoYzLnkN2wCTINtSAuDBJzJcjpNEP+zeG56TOyf1MJ3WNn2Imld7KvbA4CaPXI6UPwa1OA4D42OhlSqDWpPo6Bj/9kCwfc1vcvJQ8zLzEFt6AG053vCVPykH6wZ+bCMYfXGUJcRyLGVvoOVILZREjSRGRI8IiSCytXYLbSwoutruPhfEVCDualBGSv/K37kcxrAE8qlY5IsKTzrwl5ihpJsVr+Nj3D21Z20de79o0yfv0BNVvrWq8W1jGtviPDonkwLEr3g36ZKos2b6HoLNgcYihlPB0cOG/bH5PIo6SXEQ5N/3jEhdQF93MwfbDAAg40ZoVkpbXH5a7NSOqIpSoSxjd932w7/JngNxvVz2QJBXNoVzYNJO9BZJM71gDrgDQyQ1tZgaf/zpRKbHxsxuNWAvo9OK8I3ECXPD7MVXvb04wvSmkj+rJLcseamIwrAP0n1UirpQSg+Z991ynqKNo734zbJY2IScrbkSNVZFLNsjwYm1DLg0xjQzmnb9SzdlA0HOMWuvw+o0nHzNKaN44Lr3iRAneb+v3iyfGZEnEkWX6wjSqvZf0PRO7XI+Ycellhsfr/4CRUyqXfnUIrNJ32I8lcCilvWJPTSb3BV8I+vMTuCoy24cfhbMtF12GXhXiJStab8lfvqpWD7PPTLpo4sNzSf18HbClxPlYxV6+iYulEAk+NWiAlRMa7QC467W30ZuHFY8OxxWultk2JaFA3EnBFY/AZv9+KAWhXMp19xtFM10COP+d7GuRGIpFf530ovLKpJIMcdbvxFsatFCi95Uf78KEZNYbiE0z7NBnQ5yEFlTM77Cj/kzDg/TEPqJ+mRq9GS9oAB/EUbjjHrHoq6m1NqtFZ12SeUBSac7xUwQxkJxqyPKjwWQsOl/McY0vhEDYSdLCUBGuMhPRWsWI8sx7i4Q7c7rUGGYb9BcKrhmSgQ==,iv:GzkpzpZlkCpdH3kxpcC+EDndMGQnksjCIg9ASYq2PbM=,tag:Vkx8t/LD1ZXymvcrV0mmBQ==,type:str] +MAILCHIMP_API_KEY=ENC[AES256_GCM,data:DfPtBiQU7sBnGFp1AG95fKjuSIZCH/bSnWAUbQqEOvY1C7GS,iv:8Vhj/tDeDBemOMNNHCVl6scbgLyxOTxOIW5HqAq7ehc=,tag:gZrKJd+f4kM36dOAn8X/tA==,type:str] +MAILGUN_API_KEY=ENC[AES256_GCM,data:x7ha9jX+olLjvHuoDUb0Bn7uZjrM62wk7xkEpEW2Kmsd6xFR,iv:2aO4BM/bjxCKgrre1Neng8MS4sdKSey17Lfch5l9tF8=,tag:xr8G6Jet/DM8eYo4suGm4w==,type:str] +METABASE_SECRET_KEY=ENC[AES256_GCM,data:JfJHsOYAPaVTde6yFEb6qlER9kou0t2X+gpb9KZ46IIRkoLhr2oRpqtyO3N7QQ4OzcW1rmBXoTFhXJ1XYnVfZQ==,iv:1FQXjLsvmB0ISfqdwe4aWN7KszwXiWEHMhB7cUCmWfM=,tag:X5kqYw6lwPWMMfnjAmql+A==,type:str] +NODE_ENV=ENC[AES256_GCM,data:dDeYiotcOtAvJw==,iv:mFbJTYdhqJfPTI6qlodYRANbmZ8KdIDLIEVrk1SF4QQ=,tag:vKKmp5d+aXAEMy4WUhswtQ==,type:str] +PUBSTASH_ACCESS_KEY=ENC[AES256_GCM,data:Z/jzwKQ=,iv:zuxbtT0PRcJdV0DBnqqzwau8ndYB+qyuS/Q0Sj3ZMLg=,tag:pmWCv0LaB33q8CgMGHvY6Q==,type:str] +PUBSTASH_URL=ENC[AES256_GCM,data:W+Aow2xuioT4Xs/Vku1hbwVv53DRdPtp,iv:vMdeAsPYd0/Ofjk3XzPpZzS3dXLiaeWCGXJYsrjxSSg=,tag:iTF7lYlOVxtho9OYFg5JjA==,type:str] +S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:JCymsNIz0siWDBvmRX6RKSAa5U+MFSHn/22wsWxJsoGJPy8=,iv:1Al3xEKSRkm/sMJ50uCLzMPyNACEh+VxZi7eWz7jNkg=,tag:RCT2TzCJGQExylvH4jngfw==,type:str] +S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:QCdQ/xWAjlJc8UvsCkBdJBU1irk=,iv:/iEcFNWfyjvhe1ykRvXbCZmE9YQpIlEqJgKieOuL70E=,tag:AKHlJBiq68F3m9LlCnRpCg==,type:str] +S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:x2kWN11QiNPPgds9jWbhyUUWmaxyepabQMzSzPFpg0Qp/vqU/dhPJA==,iv:3E9/+OXAuGpdIZG0x8vbsQQMN7iNmzlE+4G7gLufNu4=,tag:n5twpJRT6Xk88i/lpGnuTQ==,type:str] +S3_BACKUP_BUCKET=ENC[AES256_GCM,data:0IdiGzCbndMI65k=,iv:Dnmqgyp64xNMIOC6cJ8z3aEgT0OPnA7uXWg1t+zJNUQ=,tag:bUtBfIXafmW0CURU1n7YMg==,type:str] +SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:HID+RVjnwrsswMZ8AD1dQRV78L3haOIWr7sVCiyhZ0P5d6CcETGXYGUxr0oTlMLSeAYZQNizfKwEh7up4ai9YfNKIy8rCnPWCpQnW2+//LPykEZWj1rHtPko3/+8Xnx4Z7begPFZIKYOz4jl9q3f9WtPIgEl0e+cIbSbUQ539NbLE/t8hOe9pSgH2P1CgjNMFjDNQd0WTXNtZqcxffifRhZ1EWOy/WFf5sb+fvKkS59FU+oXL/pr2SFMuQ==,iv:uQDYVb4pRg3zGC/gDdfEcVmIpieo/u2XfSusxeZTdWI=,tag:T0O33tomfY0TaBnGVWdS0Q==,type:str] +SENTRY_ORG=ENC[AES256_GCM,data:AJts,iv:NXHDQRJBAdI+P3u5CcnOKHeOqpG2GslsIuII39w1XL4=,tag:vsvbGgSGh09RN/xGgGNZug==,type:str] +SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:Rro=,iv:c+kPTOTBHo0OgYTXX0x6xY4L8j5RNFCfshmBwG+v+Og=,tag:4J4ONcGc8VKAM4sKXOGFuQ==,type:str] +SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:VxNVO0JwEm8ranf4Hdrppav0p1IQebS2Yuw7x7A2VhAW+AH8O632Y5NlEz7W1/zbIXTslBqxTQI3MAeyAwTRlNxHrwSojticjNwRJhq3Ww==,iv:qiOjOnazNoDB8tGf9SCkcSTDW8oedqPQqCLRBccqUTE=,tag:Dy84dihv6uOD4miQoBYRHQ==,type:str] +STITCH_WEBHOOK_URL=ENC[AES256_GCM,data:vovS5qcNe+vuq3maTMYxRQKVSyydQ4xXzLq3coejGebf0T4CmtCxUlmsPczVJ67rZWP4Dl/cmUYEWWojL4HTvDs8Py3B63tHoORUm9E9HkgfPDiR7WSJPKYD5P5/TBsyTVwcGRYFUGsn9HeaZDIXGieBnnhw,iv:Uw86Nc39bUFaTjgDIwjwoVJYivd21rg6AQF3hpz5ZwA=,tag:e/HO8V1KQ2kRFA4/40G8dg==,type:str] +ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:DmA7rVvZSCe0oL5sNwWysJXi8HM=,iv:ufvVykeYG01YPAoRt91LTc7YaG9UPHEYPmgyTraWrR8=,tag:FnzRFytfBxJ5y9Vaw77agA==,type:str] +ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:ldRZFkFtqeqN5VdSIzQoIBeMEIs=,iv:uwCRPwPox8k4iQTtkeWu1FJTtCfsz7dl4sU5z0bT6q4=,tag:FO5CjWXbgE53etYFuvwAMw==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAybXU0NytEV1BOS0hDRUcy\nR0lXenFBbkxDWWFLMEhIMitsVkpTK0JsL1NZCkpaQ0JZZnFsVVFXZ1o2bHQ2dG9G\nSjVmYkprd2hOaW5KZjdyYUh5bjhTdGsKLS0tIGpBZk4ra3JaVk1yQVFaeGNvNUJB\nNTM3dmpPbFdkT0FtZTRnRmp1ZXBCcDQKphDH5JO3MN3YIF8sFI+EFoy86ILfUMhL\n+C7lR4fFdXVwckMhA19FqtaGgljLXIMaRvzV+ufw1F/o9XVkcv+npQ==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_0__map_recipient=age1wravpjmed26772xfjhawmnsnc4933htapg6y5xseqml0jdv8z9hqemzhcr -sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnMldmQUVuYU5LV0ZRZ1ZO\nUzMraTZNUmUzdWtPbjljaFRqODkra2N5U1hBClAzNzFIR2Q5TGVGMG54dkJlTGN6\neUhpVnVBSjZlRk1lUXNKa2JodkZhQ2sKLS0tIGJzWGE4WGZURkhxQWIzN01tN1Qr\ncURZdFVscU1oVmZZMlNXU0d6UUxIR2sKTFbJKz5+UGbG0pkar5hD1TjCmoC7uiJ9\nK9OMq0HndsShbEi6gh0GFUzolf4e7z4XE/yQCw0YUpmtL9oz+lTJMA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmdUllaVE5ejRHTzZxeFVa\ncWtaZ0czc3ZjdzkyY053eGJxei9vVU04SXlrCkxqcnFPdHdhb25XK1pQVitKL1F1\nSStObGswa1g2VmlCenZaaWQwZ3czNkEKLS0tIHNZMVNEREdOclNiUUNyZG83ejI2\nL0dBRStQRFVPTk1HWVlZNm9mTElkdUUK7zPbh2SVW6Evawz2Y8201VMEeY6rgfeq\nhKSGHvozM+isEODa688MTYnbA6Maqo9bNxy3TE3jQK3MYUBcXM+vzw==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_1__map_recipient=age1vhftscteyrwphx0jpp0yl60xxrjs77jq05mkzv88js7ckc926vcqepp2cj -sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2QlJiT1AvNXl0T25UdHdx\nQUtpWEw5OHU4YUxtaGtkTC9JOXZFZHl4bUhnCjFDa0ltdWNBS1hrQUtLR2N5bG5L\nUm5LNHZqYXQranpSRmxhY2Y3c1ZwK3cKLS0tIHZ0NlU3NXdicjdNb1liYlRRS3Jw\nUDJmYTM4L2RURndSTFZVYlA2czdZYzQKm7XuYNpnd6VInJVS+lQLW2E/Vycu+B22\nq+dyRpO/7GS5FVHF3JPwy8d1I0YN9VEuS+wi6uDPrrFlI7SxIMEbdw==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTTXVlWG54dUVqN08yQWxS\ndytEYVV6UDl0dHprdnAwNVhVQ3RuNmpLVUFvCk5ONTJxM05aUlAxbXl4Ty9TZXlF\na0lqaHdqTElZVzVxRGk5emVtdzJIaE0KLS0tIHpxMzVBZTRCVEFxOFdnOVVLeG5D\nREdSRXFNdmdLd0tDZTZwdHpmaURqeG8KsyXb6h0baCY59rl8I3opWja/RhD4Amij\nVv4YhrzIcGTNQu1DBz7ULXMs2Q5MKCLLeR3oFmWVKUpRZKZacnmOKw==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_2__map_recipient=age1slx6e48k7fre0ddyu7dtm2wwcqaywn5ke2mkngym3rpazxwvvuyq9qjknk -sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwcHBhUmFsam81bXlXL1Zr\naDUxL3JpNjltNXdvZWJzajFyL0MrdFF0NmtRCm5Jd3pqbmxLYkJCZ1p0ckNrcHkx\nNFhqeTN1R2NxdzR1enl1S0ZOL0hJQmsKLS0tIGhENTFTaStESFVrbTNFNURkY3Rv\nZkRyenByaDl2RG02QkFydERuUFJ6SFUKjFPPOxdVOKA4BeyC+ofhaZ/0eC42Jm67\nb5mLGlagyYKy1n/Tc9/wpfkH6wwqPCVcwdKB1FnDI1nOKCh5GijrCQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiK3g1dEVpdERDY1dzcGd0\nUno5RWo4OVg0bU5lY2FYNU1JNHl0UGN1bUZ3ClAya3JjWUJ3bFhGZHJyQys5RGNM\ncDM0Njdtc09XcGluUXNRc2hiMzZRSW8KLS0tIGdSTWlBMmN0S050d2Rva2tZa3Zh\nY2w5SG40OWNjUDlmNWJSZkRKZFBVV0EKQU1qebh08Sh0p7+uyOMqO+Sj12Ck3gVq\nexEduwuGRZB1EtxONBKQwfAuVYaCbQPKI9kaajkz3FzRcFkYnLuOaQ==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_3__map_recipient=age1vfhyk6wmt993dezz5wjf6n3ynkd6xptv2dr0qdl6kmttev9lh5dsfjfs3h -sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmVE9LUldCL2dvMTVBMlMr\nckROajhlU29qRmJjT1dhRC84b3FMcTl4Um5jCkV0QlFwQThTbHAwSkg2Y2lGSGc1\nYnl2THVqOE4yVnBVL00xRmFzUDREaVUKLS0tIHJtRWVOWUN5M0pqWWxpYWY2ZkMz\nVlBVaU9sNWx3WEJIT0gwMEVsOUNWNEEKpTwoOFwHVIOBFP/YXNPClJ9wyjhZFX3v\nGkYdhyWWY5/Nanje4q9fQ6EXO3FIopZ91z1yFAGRkUmqGNTcFV+zUQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsN1BOQlo4eWpCZHVPd1FH\nRzRLa2RrYkIxNzJmS0d0UjJNSFk2bkdLRWs0CmhZTEdoMk9jZCtwZjFKeUNJWHM4\nTytGOGJ6ZUE4OVVHeEFLdUJXNXd2dzQKLS0tIGR2YlNnd0s2VWk2RUV4cmR1RTJT\nMHFTcks4OHRUdlRsd3ZPdE1PdEhyeTAKZrV65RaesOMr8uyZ1k2cqjHOxFGBUuHO\ncPvRvSRQYjAEs0Y8oj8GLldFv9pOTbd42mGYQPGoLsLmjfc7jz3o7w==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_4__map_recipient=age1jwuvzyghfer7rx3qtqa4vs0gxyff0sg6pqgmqvp5zlhnpmvrkdlsdha4kx -sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGWTA4RVlkZkRxaVJUS0gz\nMjBTQWtzOStXNmxzYXFCYWVVZjIzYThCbVR3ClBuVFFyMmtZeWZRamJoWXc2ZmpL\nejEvRkVXaWlMYlk4c2kyWkNDbVNiNlUKLS0tIFRPTTM1M1U5dDFnakVqNWVtTFFX\nVDBvTFNmZGw5SFJlYmxTZlZoWFlMMDgKcuU2UfOTNJP1+TdpxZs6M5gyBKve8kdL\nJR4srLDMF2A7Ul3M0M46xDfTpHXVnRrBIjMSNNweE4R/BJWYMkyMSA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtanE1VUpyZ3RhbzJkM0w0\nYTNLd25NSGZwdUVUU3hUTTJrbkFnR0RkWVFRCnEveHlIeWVjNnBDNGN5Zjh1TTNO\ndnhtUXR2bDJYVjdlVENqQlVQZnNOL1kKLS0tIFN3OW1jekhEVTd0YmwyYU5tLzJy\nVFNHUGFvcjlZb2dITk1kbncvV1JCRjQKU5M6fYbiux5buYFoR+NZBJM8g6jHnyep\nXpwC6ZEGnzpj53uwPEsIQfvTLwQI7fWhwB/QiOIUeAbnFCu9kLQKdA==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_5__map_recipient=age1pgxk292zq30wafwg03gge7hu5dlu3h7yfldp2y8kqekfaljjky7s752uwy -sops_lastmodified=2026-03-04T10:41:13Z -sops_mac=ENC[AES256_GCM,data:tScnHSxRa1eUroKIP2nedbN69c1nPluUc1aMkc+PDLdYhcIzH5jQyh4XcjmX/iFWkc4302Iocl6Gp2eZXHwi7VkXJnae0xYRS5UaFUuqvlys/dp+EpijZ9Gd85yfwYcddEBuW6eHWRiuYei9kzENcA54FvS/evWEXZcZlpX44FI=,iv:pvjM8lc6vErFDqm2NpsdGhjHNcvGFydittfHV64eWwQ=,tag:tf/+jRtdHR+SNQkiOb3qlA==,type:str] +sops_lastmodified=2026-03-12T19:48:52Z +sops_mac=ENC[AES256_GCM,data:MdqKcUG7s4M7LJDoCcNrf3ANbm6ORmCJUR29f5tZYu/hVoNGKNsq40vYAOfjRBmyCGuis7qLHU0b4yNFjLlCeVa6rISDUTXq4U8edjQTd7y6RZZ9t4p1rHJ3TSG8PmmwshphpAd0/PB0xoacYFeK/UrYuGU+T8+qSODuCbJFxZc=,iv:ktC7AHDfwwhCbd+PYYHTF2p21XK3dEJhzGyDCD8nvqo=,tag:QlGQmcA5zmUPZsiYA8Zsyw==,type:str] sops_unencrypted_suffix=_unencrypted sops_version=3.12.1 diff --git a/infra/.env.enc b/infra/.env.enc index 516045a60b..4af8eab2da 100644 --- a/infra/.env.enc +++ b/infra/.env.enc @@ -1,54 +1,55 @@ -AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:hA/kWddOh55FuPkha1j7PMPT3+rf6TG2rcfkPs24tvkxj7+ODUpvrY8K4+Qr4JrN25bE2aJx1MFOV1FyrQrDrQ==,iv:WsuSzpnq2/vVkeH+zJumxm9vD0I/CUzpHQPereUtoqI=,tag:W+QYCsed0zHU4yhZ4iYiWg==,type:str] -ALGOLIA_ID=ENC[AES256_GCM,data:KbH+Faiv84BJOA==,iv:3hOVg/koA+WUUsnDJf9qqVUWlrYioGPwXCtloJP1OB4=,tag:BHCJymiMo1OCKqI/o/xdjA==,type:str] -ALGOLIA_KEY=ENC[AES256_GCM,data:2hIGqNKJO7/xaXCClG9en4UREAk4qFxqyO4QKvQedW0=,iv:aLVvX6qv4/uMpn1NWwqC2LSr1ADbOzJY7gN1upMNQYw=,tag:o+lOFNbO08DWeVgRgOlDlQ==,type:str] -ALGOLIA_SEARCH_KEY=ENC[AES256_GCM,data:4Gg9CWgK17ua2Ydll6OdaEn/ttj34we/AQSu6nHzbc0=,iv:t3SR0lTuIk1n75CI3IxLQwl4NT7uHR2sBu40B5QpedM=,tag:f5G5EzJkqmq3mVaRCKKiHQ==,type:str] -ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:j7m2F6FDf/D4XaC482OlPjn7hrMxJ6w4V81Q/ls0/Q7eHn9RH7RV0W5xvyPlf/hvSvu26zKHrE9odXrhloh1XoeRqh05Vee8qYf87fR+M/Mbr0g8N5j4DlnixPYgzANsQzZlVReTjWqKhMgPZaug10Y6KIhzQt/jcQ7zbHKlhw8=,iv:4Ot1UKDw6giuq6KXwT/dMlVwi+HEeIzm/mqL0tbCvug=,tag:pKAGvWEMKsscZB0Bnv3OwQ==,type:str] -AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:Vv3mBT6tmPF1Fv7Ij56qdsLhuOc=,iv:r1ulHHMU+JcD69z6aeOeVrGPrjaGs9lxQW4e/knHZH8=,tag:VhftFdREKtGmBLARk8JkHw==,type:str] -AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:AznGDzO91Sx0ycktYYgxbyonfuU=,iv:VyacwWsRghNxxcxm9MJioWtlJFwkBGXBI6OJh1ETpl4=,tag:qjbUW6x/ACQKLKZPBMJxog==,type:str] -AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:OMbJ8lwDvi+VOM3P2apoOYu99yZoEnh0ycK4o8lMDmQ3ODR68fbJLw==,iv:miMfFL8MqYPzZDd1CyNjQX7xewo8ZNL3DYYkCL75JeA=,tag:+EFWr2J4vHiEqVsCzQWIwA==,type:str] -AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:1l/YEtzSJud1PLIeIR7QBDmN5Mfx4YxzgGZvjyKH7oRZLyRqkneQBg==,iv:RLhyEAZh1hRUwdP1Gzu+AxDm6Uqr9/IUsGUHOYHtqd0=,tag:8kCiIdra2tvxq+QQzGQw+w==,type:str] -BACKUPS_SECRET=ENC[AES256_GCM,data:Sql03vQCpJV7u6eDuiWJmB0QLxxnL79y79oXgnUJA757IwUJw01njcyMbTM=,iv:xQH3Mp3Tg2IwOGlXa50GgL+AobTj9x2QPLnc5qu436U=,tag:mMp9v6CJuTKuXvUSSSKT+w==,type:str] -BLOCKLIST_IP_ADDRESSES=ENC[AES256_GCM,data:lvT/nrbMy0wWMjyfBTCUOE0j5M2t,iv:C2dPibqcIjbo7eCbAcIzlTB2MXSj+2NHJo60i5Xdpf8=,tag:shMBvDpKCGXop4J8m73f8g==,type:str] -DATABASE_URL=ENC[AES256_GCM,data:jMHWvVASPZKCkFfUos3q/Wk0VXjohJLC2IEyG42t1uNVnm+Sdb5JGFW28Nc=,iv:gb7scVmIBTj9IYxX5rkaawem/jdqJGN4Uq/Syhi+tOk=,tag:to6UVXu8p2D7OjAc7Zia8w==,type:str] -DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:qlvyzy6XjigJT1Pn9IdmPASNjvQiIpj+vDQJ6kI=,iv:7y7lMScZlhI7JB5SwYHnpSbCPl3WOXprPI7SZQlYck8=,tag:kYdmEHvVr0ffGIRp2LJidQ==,type:str] -DOI_LOGIN_ID=ENC[AES256_GCM,data:Wchn9j1l,iv:sopFrwhImIk2fS7IALnWIXP1w14qPz5ZJ2GohRBUpSE=,tag:jbBmV9EJjEPZBQ2kmFIl7Q==,type:str] -DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:kdIJtqBUtqlD9riow1UTp58QcdQ=,iv:FvcWM0pOwQD/3F8nxPGO7mMIUyhpQhv9zvfkHK3vURE=,tag:6zUd6YL9mJQrG4PiNGou1g==,type:str] -DOI_SUBMISSION_URL=ENC[AES256_GCM,data:CuDxdNJ5YCqAZ9WmZAFlvf/qQvKU2zodP3m9FhqJJekr/4TYwk8b2g==,iv:9sXkoUuRvwXzLX9Je3o+1kK3hdqlTxpH3WWMg5q/hK4=,tag:DoUZzcIjNf5xoS32KBrdkw==,type:str] -FASTLY_PURGE_TOKEN_PROD=ENC[AES256_GCM,data:dzlXOit3yOcZs29NGzjfeUL9VtjFJMSHKvCrZqsu66g=,iv:7Oj//Otd2iEnTCxEmycC2yIUSaZ47RfGDyY+IyrilGA=,tag:iP5ZrnevYHUOElZ4DR8AVg==,type:str] -FASTLY_SERVICE_ID_PROD=ENC[AES256_GCM,data:jmswCx0lNnTUrKX//RcMRjkc4wEpgw==,iv:7Nboeg22qJAjD9/ZRH+3Ods/E5SPRGC0jEmckze4m9c=,tag:09+53ISwU9NGsFY+KmGmqA==,type:str] -FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data: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,iv:JU/mUzG/BboSDoDBqNOvebAlMdh3UleSkq/VJlE8Wpg=,tag:2jTqaw03TkYVwLs5sfLl8w==,type:str] -JWT_SIGNING_SECRET=ENC[AES256_GCM,data:bEL4FsPs/UoN97xbxft6SSAJdg7eSFcOhCSU5hEa+J0NOucN99FtnIV8jNrpZ3RlO2j5KF75xeWta7wKGKCOC7RblUP1taSgplNqbs8+uYadVeaQhn1mViUv04Ci93qQWkoH1HqvUqw7Z86KNmHvkyQ8/eX14XOE7HZfEVBv9TNItuswJUdIuOVLZ0JP86+d4IVY8wGlfI7Mfcf/X7TUYuEUkVnzpxzci5P7ln83wwaNPR93EFqPRG/duMacdZdtorBAiNacohB7E06CBzrx7swVTnWk6OQaowUmHYcLtmeWcf9N3Efw4oTg+ZE312fmIdoguJtSCiIGq8oDXCaZY6jF9RrSdrzHJPrIGKS+6aHy0cw7l8teDkr8qnRe+BvZVDu8heLK4GrL1xGPJw6z9vgZUtIRoouQy6Dmw6davBHsisIp6cTJgxSig57gOCypkmFhKE+7+QiySz19OYR5lNuaVAopVDE255CAB3dEgZIdMhzJbYiNMLg4W8q4c+GnRMMF/UmbFebnHVyadjJ5duWS8FZNRadLDaxJXUUNl+zd8vb/t+H3xef9uCWptXxGke1n7EKBgwgZ2gMZVziN0ZEnGiloj3QGUS0lIn85e/775miBk5ALidrLCGJIPXbD0sBN1UxEn/sWT6NAtkQTWZmc0QltWDmaMA5bbm33Cjo=,iv:22oUOUzQJUzQewKZen02A4doDkR7/gMShwI8x2VzsQE=,tag:B/JxvKg1vh16sgI8DLsJ0g==,type:str] -MAILCHIMP_API_KEY=ENC[AES256_GCM,data:mrHtZm+xddW1H/UCjMMOxCjnQUbYOimBNh3FjTMfSBgZNM+a,iv:ONBsF1SxlLxViHuz+Z0PVJstA1Jm2ywhJucbaaUbB7Y=,tag:PLEojfQe7NfKRM/PXH6vgA==,type:str] -MAILGUN_API_KEY=ENC[AES256_GCM,data:yQ0TgLgQQOsTQ+dOejywF+EWCHd/tg5/wC1R9GPAfWxl9FTr,iv:B2dcENNngHeBCat/A5PcfC1Yw4A4+VtcyPlmDsV/a48=,tag:dPi3wrPzmSwuzh46q/cTsQ==,type:str] -METABASE_SECRET_KEY=ENC[AES256_GCM,data:cUkO+BJ74/OBr5i3wXNQIQ1IRTFSAreDhv4euUczEWidXzSC2kmugMCXOloSrrHS1PylV1my6n1J+/jqS74c6Q==,iv:vf6sjwkCQFZIa/ic++8iFsOjQuRjf1UIfrAG7p/pW3w=,tag:uRyhKQ2wNfmb7QcPkF3R/Q==,type:str] -NODE_ENV=ENC[AES256_GCM,data:X4q3p6vH/DwHNw==,iv:p4MNIJTm4vdCIhiUkDwPd6X98gsKOtoYovECHVCDN7Q=,tag:4cYCkEEocuN5CPeyXPkBow==,type:str] -PUBPUB_PRODUCTION=ENC[AES256_GCM,data:FpzZEA==,iv:jIXH0AI+TQJQt8GKDbwTXiKGfJm6RmYGjkEGcEukQ70=,tag:+tDCBmOfllJDf03NB/rbnQ==,type:str] -PUBSTASH_ACCESS_KEY=ENC[AES256_GCM,data:IfLMfBk=,iv:uAKqLc6ow39+++dA2NB5tsAlUxkZeFIWxwq0uUYF2cU=,tag:xH9oPOGlMvJVjPK0KUc0NA==,type:str] -PUBSTASH_URL=ENC[AES256_GCM,data:q4Cvvn5ymSCvySyU+4uHwREdsoZm3BOm,iv:NPrZoz4Ff8yXXaIx57B56CLi5MSJqGnb5pG1FgJk7IM=,tag:LcX9SQt4vpg4intHtE6PEg==,type:str] -S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:tDfHwYWJ7ZZ/th+ljl26E/S7AxZTHbXIixUFXeXUiK+A5EM=,iv:vWI4dPbO92/H6YSKIocwoCvU925ug1aWlaONmQNRjy0=,tag:dpbFAcLkf8QpNY9DaD96dQ==,type:str] -S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:pheZ+88snTHvvxpyd8FyoX3NVFo=,iv:6QgdLDDHu6m0WgBwLnwOxkaO3s+h9unQoW5wNe3Rx1o=,tag:Pvo2il+CPUaHxqxiRnybng==,type:str] -S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:u78ms7agmGOt5sTlpK05Oe/MfXg1DubWNPji6pjq9P2Mi4j+qzB6Bg==,iv:GCkIUDv/UFCPhrg/GMT7jcpoIfLvtrUkxOOS9cRYsdM=,tag:0qXWCBUN1pAnGwByp4vP5w==,type:str] -S3_BACKUP_BUCKET=ENC[AES256_GCM,data:os1VAWAHc2DTyIw=,iv:FcXfX71g8gc+iwKeedRNt9JkwK2CmQCRZf43ZG4nUpI=,tag:Gob7lZaDZJfFnwYpOU9olA==,type:str] -SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:KSYoV1EyE2Rpm+oqqRrj7A+mb/ASVlnem+oBzZqL1gDyfhLhcGWYpiAlzWNz8MQvGfQYM1sxE0JDdliv0Qlvre+rDGAUq5v0h+LjG4d0EyLWomoYeR1IVI31xcSnEQaWbJxiqFj7pQNMe0fuevck9gJcviO6SzXh6grmu1BDsW/risAIHG059eXkmffedxwgC9RtkgxLoDMJkcbIhwg8Dlvlwdu8EHkyxMgj4+3aZqaW3u6HepmFNJrPqw==,iv:V/0pvakHI/qwUmyu392n6+Hd785VQJbzreygjP0lUtg=,tag:9PxFzqvG2HXX9xyDqylN4A==,type:str] -SENTRY_ORG=ENC[AES256_GCM,data:iGFi,iv:rMQZLu5R3qBgGUS4oMDTau2dhy+Hzd8IVN4r5jGdyw8=,tag:VTNSmLjOKeqN82VgQKl28Q==,type:str] -SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:9ko=,iv:sWSZUMWDIalL0nGC69zuLTPK7bxOVFDqxljiHhp92+Y=,tag:bqpStMDqzAvBp3CbemXugA==,type:str] -SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:P+rv8LzZzkI4xKyq2buGshyhC7WKnaKH+Zoaj4SkcsWMFxmbBvKdRP6U2ifPCP96euYWWEGol11QS4NAlAkSMCzkAa3OGQCKjc8hOUg5LA==,iv:QkzS9SaicnvuDMyrDWMoeQMEjmnbSct9nHM0BdSs8xk=,tag:OD8oq2F151aIgQl0yb0mJA==,type:str] -STITCH_WEBHOOK_URL=ENC[AES256_GCM,data:WxLdeu4x6Xj8iLs6p8Y4maaOVeENos1uvKVff4dIOrJ9+cMZ1m70V2iSzyOJHsV6NQtK/F/toKoZykfORpr+4KBahQaKf0Ih7Gcru58XoEITUeFw+EUm2hIp62eZqqzKa1eIQx2pKhr01Y0dLeusiLCviTsN,iv:B/MbWVvC9/sCsrzvxyPR16zBoa78UIZLOVak7RAvR74=,tag:7okS0rPusVlduFl2iZfrkQ==,type:str] -ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:SIB51FkqbnTXicjcbunt3dREWx4=,iv:3Tu2wv3/Tk5a+CGir4iP2pv19i7Bj6b+bu8nT608EYE=,tag:Il5QE8i4F6PdD6e2wMgr1A==,type:str] -ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:2FX/MRz1Lgs19bKGIjl9a5KsSNc=,iv:7CriioWYX9r+lY3qapxtTBL6SJQtxvkVaqun2R7Xa14=,tag:XNNDPRf495wFGtW0t+Wrsg==,type:str] -sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiNEdnQzZtSk94Yy9UNVFm\nYUo4NnI2VWNTMnRtRngrbUZaQzJDcUN4NUdVCm9Qc2hPUzJBWkcxRUFnV3lLTXZr\nM1VRdHI1R2lkZEp6TmlZTDBnRWs1akEKLS0tIHBJNklJZEpISk1VeGwzeWhyRmJm\nYkNKWUx5R2JnVXFGVG5NUHBXd1hRZ0kKliNmZjEg6IQqD3nJRmxlJwkQ65Gcz7Ew\njqySJxig/mbebmLYxK9hl8WStHH3rUhZ+OPy0oHK5vxV8ap8ySw5Eg==\n-----END AGE ENCRYPTED FILE-----\n +AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:ta9C49NPwdK6Piz5rpE1/Sa+FqdQpohD2NsMqj7tnBbeQoptG3slT1uOXMMnWzPXNiZ3w8dZsG0hlv9fRe5qZw==,iv:x9fZ1+RhtBn7lO0T/wipXk4iA+sqFRKunGGfBiegiTo=,tag:RLgbemqpEGZ0bShAyboCJw==,type:str] +ALGOLIA_ID=ENC[AES256_GCM,data:VkxNwKX/515kKg==,iv:BxvvCpyfjONpH07vs4XVnS+Fj5b90osu9nK418bS5FY=,tag:cQVxSrrLZkzWkMC/7UaUpA==,type:str] +ALGOLIA_KEY=ENC[AES256_GCM,data:lC7v3ReCfipO9SYGnTZ6E42sPfD485NeZuLltWcwEKA=,iv:TnrVGUAhvMQs7/hgUXRiDcf3frZOhap/n+OxNt/pWLI=,tag:4BYFADREL1bsx39axQ+q4Q==,type:str] +ALGOLIA_SEARCH_KEY=ENC[AES256_GCM,data:INX6uVAM4sg1mdHw9QzrN3oV/LakWjtyyVpA/J92+j4=,iv:fgTvYG/zuRcJYhg+Hbcf2DrSOr/bxQBB+8nZzbFH5Ac=,tag:oTDEF/xR2FSpAcD8MpP8Sg==,type:str] +ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:vEiqWWJHtU9YHYquMgkt040WHeNWh6KPEIBK2k2oK/K9lNmP9+8z1FEz8vCab6eq1fR7NSs0El+QgIztfJl+fNwWmUz9dpeggjyeussi+tpETefSCcXBDlWaQ+ddpx9e/JXik/KztumBlmO6NVoqjOformFpV7QAaZctNTsTsIw=,iv:XvJTEf+fn1RSgZazkkUlWOzYcl8MiGQitS7DHEoYh5o=,tag:RlROFh6t8JQCe6CBdTalBg==,type:str] +AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:IK7TnKSuTXeCwR6iVNkg0GbLMVs=,iv:XdNnDImr5JIBnPNfrao4bHoaYS08TVDlOYxPK1Egbu8=,tag:JL1hCrJ0T71zOwNvPtHS2w==,type:str] +AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:dSCsnX/0UM84L771rcqvm4NLogE=,iv:HkhIDgdwibioCmX+RZqyvBlB14zkC+vgS34VDA7+MgA=,tag:W5rY+xBLsRw4M839rV8FBg==,type:str] +AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:r+bSlK6q/FqOVEMvaWcJxqatlVckhy6AWDJjupmCBkGOefSINxbnEg==,iv:scD9MGhXtyflbFZlyeJFHC1a0qpGjhMHCedeKOlW5xI=,tag:NNPXULNEyMfXpje8XtNz2w==,type:str] +AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:UiwknKpVRBN9LPIJ626GyQgyO1+Lt4fpDHThVdAsjgkFr4sa5lLmIg==,iv:Kt70aIUNoofxKhYAoBW9/TLH9lZpS7kmfIYKBixnSsQ=,tag:2jfJt0QO26tzf3sYDtgJBA==,type:str] +BACKUPS_SECRET=ENC[AES256_GCM,data:0FvJ4SMhGVoJygeK8PYQK/XIc6LuJ5mCi476tzkGINFDZBve0st98LKoXkE=,iv:l3YrnTY+2JwLVCqNz0arhSKcV+iWznbYwp7nfMvgEsE=,tag:vg8ESAaFf/VihK0KxPlYgA==,type:str] +BLOCKLIST_IP_ADDRESSES=ENC[AES256_GCM,data:JnbKt1oRRwND/Fp5DHuw04Lli0TJ,iv:bZVB2xy8Z9p/qsQoDHTMjQUt1cq/aAJHDADwZbZHPrA=,tag:PC73yITJrJDCqnsRRqPKCg==,type:str] +DATABASE_URL=ENC[AES256_GCM,data:3eA+a7T2EUQfRok0I5A31iuqxLkXmRAfKQMK4uLCEGRW8IfDNxFCrw+DXdk=,iv:2Goog+XodxEGvyHYi9Db9CIkYJsTtQAa4bFSBuKa7mE=,tag:LkVfMNfMFPwvyr1tP/Kwzg==,type:str] +DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:V9oiyXpF/+8dnPVfbpAejfkD+VaeqDSLUAbeOZg=,iv:/srEAiNCv32Ay3ikGbTlKmJQYY5hWzLHyHt41poCjvk=,tag:KVHcXLoQg69abkwHewcciQ==,type:str] +NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES=ENC[AES256_GCM,data:T94=,iv:RUhcika0mZlwy+smFIrtNu/cKLX08z/ST8yFN+om8m8=,tag:gsEttzFbz5rHCKRA1jePGg==,type:str] +DOI_LOGIN_ID=ENC[AES256_GCM,data:RrzghNFA,iv:VSU0pRZc+f5UR82VPfzInjEc7EtOAJl+dHmByqhFkdk=,tag:GqANF24LCdmRaJZv5TE/yA==,type:str] +DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:25H4D+fsNzurjBB/zZKRa754smc=,iv:DAv9fjm+rtKSmGJcXULMpYmCmky14zTl14iVRlZgwFw=,tag:n4JfqXB+gyOmOQ5poSmygA==,type:str] +DOI_SUBMISSION_URL=ENC[AES256_GCM,data:ylrz2kwqrwvhWFjNYDeup9wdo2kEHnfPjVlJqBS2O2vatrVbvodh+Q==,iv:pDLu/E+5FLT9ovUHCHW0zydZLWlNqokc7ajWyZ9g2dY=,tag:n/FuBMIvCsF3HRezyUjElA==,type:str] +FASTLY_PURGE_TOKEN_PROD=ENC[AES256_GCM,data:uPBaHRS+H6nAUhpLiXe7qtwzB4sB04d8CKfhrCNHq2A=,iv:B4oqeagQ9qaZbWnw6YQc9/dkxwTPbnBUoyoWq86th0I=,tag:QEkdpVzCikeNSnW+tS5dYQ==,type:str] +FASTLY_SERVICE_ID_PROD=ENC[AES256_GCM,data:gkt3WzExk7ayoxyKVt62uEH9e3gWvg==,iv:QfuDX0BHgwYKkmyn7U49XaqfoozsNQog1ZlmRf4AsU4=,tag:lvaJBUi5rPxFmMiIoPi06w==,type:str] +FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data:hkv63uWd257pajYjFgvY2QW4kOYnqm1A+yVDmSyWH416LkuHZpz2LEPU66DVhp443oSnxeDbbe78LAd2zFGlYR0yVsrV7tBhOlwlZj9v2s1Aw7t0aqOAdeiH3JxWZ3NcBw/+7AWhzCD9gfL0kibg2CPLCEGZ9Q5CKeto4B65Nmd9kGkr9dOmV/MeEAzIC7OrFTYlQ180frVVzDXYtQzY7EhHmm+1Nea4JdrL7tIW+x3CaTvqty62lurLySrv9Rl72ats6OeOgH7w2n9XQBc3Wmsaou7/s6Lge2aygLAdtqkTvMy0yFGHiOL0Hu5PZq8aki7xD+4+YTgPjD8RVIFjzbMn4PxsXwJ3WD47VYOovn9OOY5PtiNyIUgNSetu9AD7GVJO4UVm9WFA6qsL9RS3vXTTcARIeW56AIQ7FSFqoYS/qvhGmNkF+lMcgSD3Sdr39YKjQmlfrsw5pw+bCwMJ5c6LCtTWTM1tHgpYfjZtMQhXqKIqNt/rEi6jDCbE28vdNDTSaCtPZMfUpmiMvjtO1Xg+E2e9a/vlmcza6Pqexecuh+buMKicCkoF9EqTSlNKU+T9gXsN6XeduCCP+puMFGpNXoik+Ms5Hfwr6ZRXVvfidniSzzaZC13Pyn8ZLZlmblibloJINHqKljKbksr79KfCzvfW5EUdGN9MOlO4NFjVrVUrFfDnX9elSWBw8i7PWEGEqZOvl09tCZUju7lvKSuL86GfwdCT3fZPaWUIKAmebEHrectm9HcXxL9bYosBmtSYJAZT1xqhAVwQB0A2TK8SS2nyOgKSjZ/4W59CX+Jt/NNunCgvxuxWLXJPlElzzycFVStpu8s9aVcbr+Rmd3M3Rt0A+VcuS51vk57ABvIWhpmOsr1cc423anS7Zugzx8yc7rwtT/bqNcBRLse4R6x8xXTgmVtOAIwvNeo8wGUv39hqUrECaW0bx3s7Mf0D2uYxEwkFWdyRXIciBHOEHPi22C8jPsIASfEzR20g8FWd/5g0gV3DG1zNmSbgxPZ2mjWkNKTXdTaUq67RaDTgXOBLkKcSHUclLqoosuUsMUF5a9gFeP9QqPXFVmuW1sOny3Izklb/OKtXUzPX0Azwc2JKlhjZN+RHKzud53PJGhP4eaywv3Fj8tt4Zet6hNkp06ru9Imhsc5zual0k0IFtR5Ro3Zx24kTcWy0Nlm7kJBMLzBNd833yI9ggUKEvnAQavFEJK+V2mUJJw0larWDuI3S7mn4q1oeBgCeqxoC8o0wg2fzxUYV3gIe3WSTT0OsgzPI4EjNHt41WaNPNZjE9LJGFH6EFkR9QovUucDQ6Xc+StAcZth5p3I/QdJgnYXhwwobYgLwRnR1k5eYJ8aof+ucjrxBVdlHlPY+1mzi5UvApr5QLhwCFcT0IqwvSAiLxnqP4vau+aSy9pSkymsvy0sOjAaVJH9zLtM/vsT9F+e1UtgE29KoDhoFX/Jh6vWVqcTsc6g7jJ94vtEPxxL9DQuI1uwtYyNjPZxmCLm+D6xfxuMyyp++unhEMkw4VM87KAysxbwiAYoWJ+GrXKgQUGNDykiF1SgCrxz0JQJdYzbDpfJEch/RIiRZC7OTDuA2QnAbcJzySsLAPaQPz6x5dtDbvfnnNN8eCLWEXntx6zRsa4Xjc1r0po0k7ENqzg1MFKRpOd5Ne66CgW4vU7mmHP7Hk/nKcF8F03NpVWICauv2lgrVLkrWXJK0bz7YtFi0zbCwz+BJAFKCajNuRwLlV0x+j4ExUCeiZXgDWpCXMgnui0s4WP0+LE0/au9ACuIPMZDaMYhcvDkE0GWVfzzLCF08z5t43HBK/WBMxXzmj6Bw4oOpziObSTbbtdrei0jUBiCKBNAaxRuiuj7ccUl4/UCqicb9w5mg4GmGZgZTEqO3fPDypPYUXoubc9hHm7yUEG4bL4U0Wgm42sRZEvZYNLGLL+87eCqYCVlQgBF7KqyMO3PlD33IFYIH7v7rdxPMxPlon0f1NXnzB8PXLLmjkk0TDRN9PtdqvYtDe1W4Sw7+nZEtVR517VEKx9z5V2DULjmsIiOueGJWac8zFBcPA8eDeuDjimbrATN6fH6/9Dc+E5k+5AmmQ6uVqr0T/crYW8a6iYNZTPbmQl2FnqlkLdu2oCeJTzZSUSb1q7bgVb6FWSaewaj0LLNqhHhUGX9Zoqcp9DflK+VJ8k0gPv8If7vWRjGLSk9ptIxhpygnOUugg+G4EaSSwdHduB5wksih/MruHoCJJAVP3TAKwt41coJZ1PCthUGmpedM/W+GhhmfpQD9fntcFPNkZzHUnpT2cfQxkDnx/clTQZa+kqLIa7JynpvhqnVXl5f81Io9+pIUD8yVI29sRgluKIMNLtiOI3TfTMgiBGrM0UKYYVfvzAZX8NgQvY8hsorkYe2gFiTs4fHZwZVpH5vQnmi3nKFbZNve9c920LQubSoXAlOl/A/KIdX5mq93T4oo+/uB8W5EkhEyorMfLZgGuXSRkA9nPl4jCetdvvbr5UKRf7KLFwAU09Ul6vhA0JlPSfNx+0SNqY87cb+rURFEXZVxJ6920nioXRdhITh8tH6XXcR3hJKJ3tlJgGF+FO7Hha46zGNEIOI22MadYGkk1RmW3ep1q0ioyV00a/lZ8KPqu4NIu2XIelOtP65EErt+k7MX0RrrMAJMQ4PRY91nUUYpukhu5rcezGkph+lyc07Bawj2UQjaE4Fh80CZaghJWUwF9Q1Sf7CKGWh9kWwMcityIh/oku2BuhGktJmEsdyUk/axIFAJG2IFGt49h2n4LFWPyT1WaV6FNCdWlH3OZ1ptI/clAtikGnq+NnHbGlSG3EcKCsRjBiNJVZZP41P1k6+pVB0BUNosvopFVftQxvw9Qhij621xt2sKQiT/bMRPFtXItsnxvLFHZpj/m94SueFHSKqdnU0A/p73u7iu41OIdM/O8U5umS2NZb0HCIekxp7prDvY/KWxCjWzKQfkDONXT2HTYQ2CtDfTH9+5kEPgNmFGBawofgSc0WcsoLYnQ3wicjwjzJQBwqcxYgmwDy49WsbVrPIRja066h5l0RVHMlCwRBnpG0/Jn2Wt6edx64WCRQESpJhP0Q9CpARV2IMTf8QbvqaeVcwlAytQvV0VfAq75Zw/3/NWRTmvLZlHj0mtzko6UOw4+J5MHMs1A64ZT4eo9oh6+xxUsKL7XQliO1JnhHCnVnuwFhsMkc2zS7u1y3HvN8Zv2Bxwy8DdN8J/XXCgA0/ccfGuHcaZxq24nEkI6uTM0Dfn0Hi4wYKi9b6asS0R5gVYQilJJzt6kM07WUHdW40m2n6AMjz2Edl6EvTE8IVPiH2f5xgrkI9ImAmot1aAlz/RfQ2JA3M6WqovJj6w9bJd3hHhGx07AcWsdKudHG3jyBp8VEBf2/8Aatm+k7+xDwr5AX5f1OeihQfgCjuZN1gSQCQrTTQpFPOZ7FPKyClnu5ch1ip00pmI1KjJsikj4uma78c2T3a731LM6FfljCtPA8nD7nXig2ayh8x0kesG25kUao0QBLsTMWAIx64GQ5gWO3ZLtvrUBxjwH2qdnI0yYu9x46d53/TCGuY42fndg03+nNbJwyOWabFqEt1SATNShb9IV6732QHp64CrRuLP69HUDfzIqx5D0l1/cbenRDZ159dd0Ic/Uo/bTyzodVcuZOahxg25gfKKH8MC8S3wq6Ni9iyDFxdxRzusdF7G38Dnf7ZpP4wN1RnBpcJF7nV7FIBaVzq0plIerCpgBCb30cvl2tE+Tp9F/xHvy0xjTlg746WpR/I8NsLO5w+EYEiw7liQ3ZW9+5rmVrhG5H1odDpIufVgPz65gyugSD0j0Osjrrh/j28IRBdzGdkr8d0gWbi4H6m2WT3eES2nh75cnmsObnNIpsecLhKu9i1d5d2M2rw2ZfL+6XFlQoXQ3h0088ks5bW/Q8VyVL3tvfNmL/2rryCkLvqKz7L1DDnvUHGFOblDT6dmLdM5vB+nbZfTyjwu7hBpy+SUL/FRFoz/bU92hvqO3vk6LY1aUtgfNcjmhTHJ/UvO8hOAjtP6ccpBfGKb9gyPFp1DIttgX5becTmovxoNol8BwQ4XUqcPZ/Nd+WBkLAjQMhgfaoIg1KzYJVTfCykQE9xUXjo=,iv:ZzMu6EP+kQCbUhjL8xa4zaAhW9BRuim026rKdAAUfJ8=,tag:0wGmQ0ZVRyELDC+cULi4xw==,type:str] +JWT_SIGNING_SECRET=ENC[AES256_GCM,data:Cnx9mkYrwSYjfLaQOq8kgzFITpIGShenrYdcqZC+NGIQDqam0GlqIwY4bSALz1nYsQUq1pELQhXVzjWSy8e7p30G5xGjr3rUCinoDxRptG0aAU2ZHO8LIz+xgcUHlRwFWzq7pYaV93ceEIW8Qo6wRr2VaP5v/JP6ORFNexePyrij67Pe78ABX0mb5PCF3GmRilDOr46DixZG8n7CDx+6t0o4HgDOzU5JMZmg07/U6Uq/F2Z49kTajzK7vNSACZJwznHohQ2lEYz1zub6JQZK0bLlTmVfo8WsZrrDsy97BlwivT1f4BjJBWp+QjMlF9yGwB6mdz2loLTJGlYLyNBG+hQtyRiFQC2eQU3bkPhP/sLm8v6ckV7gRDV108tRw88TlY/ztVb5qZztwtL6+eAq4/YIgoHyu9f/Y0z1564CRqMkzRKSRIAHfpMuPRbpxDZim2Ao6lW3UsDP6gAqEF/IVqlbdOOlDOPmOanfbhrz1Eg6fyk3itl0PWc2nwkhihFJlvkNvxUJkHt0M3mEtE7zS043y8kve8GZt9i0UYX7K/VQK4SGN9iodi8qw69haRzHZNUHzCmZ8yea4O+Eawaw7cmYdhdk3oi3QvqbVAyQB55pXzKv+WrbZE0bYnLEkkS2YW3Ta9+MrohowoNRjN8Ql5PTpJdvNxqeCZQCt6+hGmI=,iv:W4QCrxLzibhr7eB0Z1WQhIOF659UaU5VgYfJd2V/sKE=,tag:+YrYbruTuJGhJJRC6YTtIg==,type:str] +MAILCHIMP_API_KEY=ENC[AES256_GCM,data:R06IpGAVCm+gfof/ZdPaDvtNrRAs9fFBo1LDfebltKtwIEDp,iv:PBEPOu7D4L1x6bnDukaKHeE6oeNX36iMWz3pTb7UATY=,tag:f0GexDVHmFkZ+aCjhwce7w==,type:str] +MAILGUN_API_KEY=ENC[AES256_GCM,data:LhfrecfHr7xSzqWRhjbpGEDjhPNX4ROv+216WQFXqn2Nfoyl,iv:Nn0xI4bdyt/R1e7EwvBuzC4FdHvYNBVBZxBKCdWYuMI=,tag:dooiG59dHz4T80IYKrZKxA==,type:str] +METABASE_SECRET_KEY=ENC[AES256_GCM,data:exzO6Wn05Jo9DpTc7X1j5FWNYupqXsGyltk9dKvPwzv80256FcQz3guR8Owxjw32spl7+NNyS6V/Os8CN5teYg==,iv:rxOhRLVYASZKtye0VPOfkxgIVGb4x/6OdJolrxp7omY=,tag:f3KHj8s2k4pkso0xWCogOA==,type:str] +NODE_ENV=ENC[AES256_GCM,data:TlIcP2Ntux3RZQ==,iv:wHyxeuZQxAoWGVUvlBIR2cWFBZZXk2UjG0lMF451TW4=,tag:1nFf+tLppT4Ij4e7JJBk5Q==,type:str] +PUBPUB_PRODUCTION=ENC[AES256_GCM,data:d8Frkg==,iv:DR1Yiu+u4FAI7x20xA6GLBdfEJFseLX7Gixkzvf9+d4=,tag:ZJyq6+SHqxdDmNHfBeHf0A==,type:str] +PUBSTASH_ACCESS_KEY=ENC[AES256_GCM,data:Q1gKyTU=,iv:uHaYuvNJpWNnRGLCxa1RDzqvnh0LRwbYSxmm0aU6mvE=,tag:nN6/b94Ze3s5/CxIy/pCLw==,type:str] +PUBSTASH_URL=ENC[AES256_GCM,data:6zlFP3n8hJXia3gz3tzhyM3dVEtfG7nS,iv:2C1xOqhEqTy0NbV6eLwA4cdv+IUBny6zzc8UzfFMSdY=,tag:a7/IBdImIT40d6gFU2FHJw==,type:str] +S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:wIkSAnkSfENqO3JMiRHnEIl2iCQhNJVovAovbeflPSGHrzw=,iv:6sBjIxGU82VL19gSRGNYoVmpiIpQBGJalFNsLxgE14U=,tag:qVd7biqUg2W/DqpwZKMSUw==,type:str] +S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:ft9IAsEFZUqiazH2arZWqV5crjI=,iv:d6d5KhNgkNeRc6bmMDIwp8SvT/SOfFdsgJ4KSf43sTw=,tag:4bsELBG1Yv1hp+Dj9kIbMw==,type:str] +S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:EsH8Osz8P4/nObLahmK0zd81NVYgJbD/x9qZsd65aUXHPFYmECn5JA==,iv:0zTIbnrLx2/yj3MhG0Np/vlzgJlWV4Qoo6mhZfTn2Zk=,tag:p/9KstYqwLfi2kCtlXqFYA==,type:str] +S3_BACKUP_BUCKET=ENC[AES256_GCM,data:pS5XxDmyG6TkYWY=,iv:0n7yGMEkmbQlkiyOu/5FNICF1OY0qhnIq1oLAsfF7uI=,tag:inQckJ+wWPRZlkEGgM5V5g==,type:str] +SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:Z5QO78olLbIImmssqxyiV15A1UmwkDwRdUEgkPqLXefPWz+7jCjyg9QIbo0o16+Dv6OSoDfwiUKwe9+SQZM/HW8jEANaB8zGA4pjtOHFwvEUuv6kYE0ILxS773YP8nbvfT0ViFMbRP6r2BTIgrNoRBlzpCNGsZwMaeohHBRsM6mABPU3qj9u6wTiZbG5zpixwbjpsA6e50QbAHQ1XTuKvpVobCDOYfY0nuDG7o6Dx037ydzbYh/G4AxwvQ==,iv:fea1BYVVhRWmGyGAmVIsIujP12hrQqRoDv3oaVZ9QMg=,tag:/Lrgo12xiCVRm2+ceyPu9A==,type:str] +SENTRY_ORG=ENC[AES256_GCM,data:I5lZ,iv:lyUBNaw8StMhpWuC/Svr/GLkVrd6JN+xv+iJI31GXjo=,tag:mrajK4V3IJKnLtwuYBq+vw==,type:str] +SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:7WY=,iv:2yoJEck0aoPdHBDRaVCVqsX61pfRPf2ngHeE3G3MIYw=,tag:gOIfyz7i5dJur7UARF7IdQ==,type:str] +SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:e+gTOfSrpAuWtj/4O+rJH+PAgiKVUYvJEO1Lhu0s08l+hq/S0mqpLBr2QixPjuzzgNlzbTWslKg+wvP0R6TduMQocXa4rr7xV7RyzTC5ZA==,iv:bKSPBA1wbZCZ5cBWxKQPfY3RapKcj7tWS8uOMJiUgdw=,tag:rCM9WvgvyWuoZ3nyQchg8Q==,type:str] +STITCH_WEBHOOK_URL=ENC[AES256_GCM,data:G2TnY6ZAjOt7cg3p1nsJTcF7mQ5wyopThI6fuoXGYYdbowj7aLz3lexPw+RFj6p2vOaT/Vg9uKV7twxZfbriTTXbvNFUCkgZW3vsb9ZX5XBXkjX2S3rQs6BdBeRQJ2GfKQLXEl0IXC9XYy6fO33NypW4jbua,iv:n+P2Fvnawnjhy/42D8oWQTL3VYZvbHjKd+yQ1GB2Zxo=,tag:qiRy5vIIbNgs3P+BBQJOiQ==,type:str] +ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:XzMD27FpGZiXcPz6jX8ng+H37vM=,iv:Ac8EbtMuI8evhdlYXdKYNbCpuU0VTEG6ZLUCy1bwQSU=,tag:A1UWdE6mUVSOENT8wGZIgw==,type:str] +ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:aCwpMGvzChk0dEiO+WSIJRibkjU=,iv:FcrdcE+wuZCRbo+1md50pOh49DKGqtyXvNloevkw+Ug=,tag:jyMnz973AV3WMK083DDFDQ==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMSE9WR0F3N3BvWFVVRUJz\nNUFLM2k4OGc0REFpaWtDcmdJZlhaSWhGNFFrCms3ZlV3TVhJUmlleC9zVG5yN1Iw\nRUpPT0dXUHI2ZENHT1NGZW83NTlyTEUKLS0tIFJBb1NDVFlqNytmaTRBNEtwUGl4\nQ0I5S3poK2Q4NTdRYmR4a1M1T29hc2sKRweypHzb5/te5riewYShOo2xNgv7YXpD\nJTw9Zd9FlF53WCK26yiwCWPmeJrMN3Jge/7GcXamXeQdz5mqcL0BxQ==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_0__map_recipient=age1wravpjmed26772xfjhawmnsnc4933htapg6y5xseqml0jdv8z9hqemzhcr -sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWUmVJekpWZ3MrNEpPSGlp\nUGsyanNhcDV6UlFrYVhISXhvMzJFaTM0WFRRClV3bk1ZY1huRVVvcjBGZmZuRmE0\ndTVRODJ4cjdLRS8xdml2Y1lWekQvdncKLS0tIDZuOW9CZmtKa2R0SkV6VC80em9U\nQnYrYkhQeFhqTkJad3RycW9VMXQ1UDQKTxPKEq8ox5dwwsN9/7aEt3nWT+xKxvrp\nj3O7RF6PpfWPq4m2Q01T9uJ3QuiUehtn98Ca5cPGmkhaYmQwwpb8BA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlZ1U2dXB5L3pPbUdJNlEw\nRHhvU1ZOWVJWNU5EdmU4VkhMd2VZTW1icEJ3CmExcVMybnAyQ3FhenB3L0FUWWs5\nTEpuQUpaT2NNVWY5NUt3NzhWcHQ1N1EKLS0tIHJtVC9NVU84aU9JdFUydEdaSklo\nMFU3TFZDV0dEWk1md1ZRS05KNWRwbVEKOEYj65+E6ou6F/0VIRoZh2DHnSlwHQr9\noGCwQ9RWXgvZDRTSxt6OWWfRJQsQqKRT65HLZ/nuB5u5rfEDOV9SDw==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_1__map_recipient=age1vhftscteyrwphx0jpp0yl60xxrjs77jq05mkzv88js7ckc926vcqepp2cj -sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4TDFQMzVYQ2RtaEh3ZWR2\nVDZ3V2dKeDBwWWdHN2lNSkZyVjlnNkgvaEhVCk5NL0FEMTZZN2phc1JvVWx2M2Fl\nV2ViS0c0bUVaeWNxQVdnbUE4M3NJYUEKLS0tIFQzaTNmMWpyUlZIWjNtNUdxL1Vl\nWWNJeUcrOGZEVDU4Rlo1L3JtOFczNjAK1r3Egjo3tK5ukTlxXtBZBldJlnIsPd3t\n8nBvpwSBoPSmROVekgoSWIT/WhLvzbjAml0AZ1kEhXoZAAIY0jGcjw==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCSHJ5dzlnbysrWEcwR0FU\nZVg4L3dsbE9YN25uZWRnZGtRVSt1bWdTRkNrCnhlMzRaYW5IcWpYT0svZFBoV0Iv\ndTFWQlM2a2FWUkcvTkFoZy8zWGdHaXcKLS0tIDRUV095RFRGUUw0TXRGNGl5MVdy\nQ2dSWmZpbDZwWXA5bWFuSS9PZlpkdUUK88xw7WRNI13oL+Y5eSRtRwrEGrGPRDgO\nY5lRNZuquztkaYDUKpdevtV0f29RKG2CCWhFnwVFp+2Ln3DlTdyEhw==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_2__map_recipient=age1slx6e48k7fre0ddyu7dtm2wwcqaywn5ke2mkngym3rpazxwvvuyq9qjknk -sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHUFdETWtsb0pZZ1U4N3U2\nS3ZiY1ZkOFExZ3FtZFNVTVBpdW92cjhmRERzCmhtR29DWFgzK2FJejNDdWRjQW4w\nOGRiL1VxRTRvcVA2WmtpZnVCd0VrVG8KLS0tIDhZYk52bmN5akNuQ0pLUC9tbEts\nSXpyZUIyN3FqcFFyVkJkMmExSjFuNjAKZTJo0nztgR6Sl4C6EgSjg1kZiS79d6pG\nl3ZIuiulnRvqhp80ckFVRIj9FtWimFOUUAz/41NN/Ct/RC6Sn2OwlA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvUEkyVzVmcXFpelhoLzZm\ndFc0T0ZPbGIrRlpBeGRTcmVlRm94K2RLWncwCmoyekJYSHQzdzRINWZHZVYrMFN2\nOUp1SVZCak1IRmUvYjM1bk9OZ3djZ2MKLS0tIDRMVE1JRUdvTERvaU1YZnYrSnZt\naG5PUGVzZWtIWnNoNDJNNUEwTVdXOEEKaHIGtc4Zp3r4KGq0sIlj/jY17NHRSN/7\nmahI0rrLZHkrE/0xO6qoaeX8C2XToi5B9MIYVGW3FcO2EF9VCatnOA==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_3__map_recipient=age1vfhyk6wmt993dezz5wjf6n3ynkd6xptv2dr0qdl6kmttev9lh5dsfjfs3h -sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGK2N0bzIrYm5rRHBDNkdm\nMkpiRFFWYmJCVXQxSVpvcjVsbkZsOUNUaFZFCjV4Y0tja29hK3N5TXVIeWg4WVdD\nNUllY3JyWjBVTGFxUS9GYXJOUFBiYzgKLS0tIGI3VDhCMXErT1dEamN4cnRvdTlX\neFNSdnFXMXc4eXFVNDVHQUhaQ1FaV1UKvF9cypiEL2c3Ky5FB8rf+J6I2SOUEmSf\nmH1WkCoyZzAAykWSC32chhBb3hAXmgtxHs9qAvtsGcvtXxfSWVCb5g==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHMjROTDdkbTlpZGJZRnA3\na1NVaEtVVTNHbW5pc3ZHODFNMkxyWDhaTzFFCnlBMUdHKzRCcXBRY1NtSDM2QTFs\nWnlDNEh6OXpuZUFSYWxyRzhnb0hMREUKLS0tIDNGVEw0M3NVYmJKS2o1NE5TU2k0\nQmpvY05SL2xIQXdIcWlwem41R1o5WW8KHIS9QgQSGdnkOnIds41TCE2TtjhVgYdt\nUYOeiBSugrnNJ4+yDvmUANMil+xCC0lNNaNTPn0Ip6eF0UOOTjOhbA==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_4__map_recipient=age1jwuvzyghfer7rx3qtqa4vs0gxyff0sg6pqgmqvp5zlhnpmvrkdlsdha4kx -sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYWlBIMnFNQ0FtK0xqNkk1\nMjkzL2VhZDhoQUowcDNpWCsxNjd5aDJrSHhBCkc0SytzRDdlS2wzKy9wdlZTYXNU\nZ0IzUERoM2REWndjaGdZeEY1emYvbmMKLS0tIG1BM25jK2N2dnNOUnBlSHhpUnVS\namZGakxRREliMExvTjdGMnhJY280c3cK1XsDSm3WkRpsO3m0SMHwB8e7c4CYkyKF\nfI0nFT56HCkKz3TmySKjNtuMW+vTFn5Svnj3WSJAdeO5rd6HLVpeqA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSODhhNXJEWUFBRUZQOXRW\nUjVKekwvQ2tUV1o4SjRwc2o0SXNQZk5CQWlJClh0QjVNRHRVdGJaYlpJZDNrWjgw\ncnZCWFpscGtyTGJwblYxWStNbkVXbHMKLS0tIG9hckwyeVMzcEVidXJ3WlZzVTBw\nWFFoLytHRVNWMERNOVFtOXVLYUlhME0KijQzW9Glvf0jGlxMeCFR2rh5U56cYdIP\njueMSizvAh9OUmy84nDMiUbm9KQtNWD6/exQjPtCTIawIU3WdntWFg==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_5__map_recipient=age1pgxk292zq30wafwg03gge7hu5dlu3h7yfldp2y8kqekfaljjky7s752uwy -sops_lastmodified=2026-03-04T10:41:10Z -sops_mac=ENC[AES256_GCM,data:qYo2ipCy5+STxYsewKuSICLT8Xe5hr0zb20xe5arSTdFt5DxeKRCwd7Z/EUwzBpC79onwXKqZlSvsR8cilH11oyb9hauTr1s15TrwQYuzw4L/ZVjI01vdeMO/65HF6qsRIqIkUVwvaQgtlptJxswWvyxAdyAUToCFOsBiLMnZzk=,iv:WfWBR37iqT/fHrxlBiq+jh8hP+TdUYYl5pEAVPJQDRE=,tag:RgZJ40vJG6B4bUuDTvx4Vg==,type:str] +sops_lastmodified=2026-03-12T19:48:55Z +sops_mac=ENC[AES256_GCM,data:st+A8Nwcx9I9i7xtx8g0GED6786JvsxZw4+mjRJr34xtFREbLBWHfL1FeEzGO1e0wpf2LbS+vsTy25SpudabIJBUc1d+DzgR58m62T4YYowERWSRETDg6drhM8xCu0Zi6926OthZhj4GyO6YIoE3szsMPaUIPVDfTPWA4zjDO48=,iv:JtkDMwUtxQg4W2l1pp0VhQA+/V93y9TLjNX1kwLw1Ks=,tag:kEriqeU0CI+4wDyoE1hsdQ==,type:str] sops_unencrypted_suffix=_unencrypted sops_version=3.12.1 diff --git a/server/discussion/__tests__/api.test.ts b/server/discussion/__tests__/api.test.ts index f58e2d8f60..872c5f5a1c 100644 --- a/server/discussion/__tests__/api.test.ts +++ b/server/discussion/__tests__/api.test.ts @@ -1,6 +1,6 @@ import uuid from 'uuid'; -import { Discussion, Thread, ThreadComment } from 'server/models'; +import { Discussion, SpamTag, Thread, ThreadComment, User } from 'server/models'; import { expectCreatedActivityItem, login, modelize, setup, teardown } from 'stubstub'; const alreadyAppliedManagedLabel = { @@ -474,3 +474,30 @@ it('lets admins remove managed labels from discussions', async () => { expect(discussion.labels).toEqual(targetLabels); }); + +it('bans new accounts that post discussion starter comments with links', async () => { + const { guest, releasePub } = models; + const agent = await login(guest); + await agent + .post('/api/discussions') + .send( + makeDiscussion({ + pub: releasePub, + text: 'Visit https://spam.example now', + visibilityAccess: 'public', + }), + ) + .expect(403); + const user = await User.findOne({ + where: { id: guest.id }, + include: [{ model: SpamTag, as: 'spamTag' }], + }); + expect(user?.spamTag?.status).toEqual('confirmed-spam'); + const newAccountLinkCommentTriggers = (user?.spamTag?.fields as any) + ?.newAccountLinkCommentTriggers; + expect(newAccountLinkCommentTriggers?.length).toEqual(1); + expect(newAccountLinkCommentTriggers?.[0]).toMatchObject({ + source: 'discussion', + value: 'https://spam.example', + }); +}); diff --git a/server/discussion/api.ts b/server/discussion/api.ts index 5d87722960..1e19371a9e 100644 --- a/server/discussion/api.ts +++ b/server/discussion/api.ts @@ -1,5 +1,6 @@ import { Router } from 'express'; +import { autoBanForNewAccountLinkComment } from 'server/spamTag/commentSpam'; import { verifyCaptchaPayload } from 'server/utils/captcha'; import { BadRequestError, ForbiddenError } from 'server/utils/errors'; import { handleHoneypotTriggered, isHoneypotFilled } from 'server/utils/honeypot'; @@ -13,6 +14,7 @@ export const router = Router(); const getRequestIds = (req) => { const user = req.user || {}; + return { userId: user.id, discussionId: req.body.discussionId || null, @@ -36,9 +38,26 @@ router.post( if (!canCreate) { throw new ForbiddenError(); } - const userId = (req.user?.id as string) || null; + + const userId: string | undefined | null = req.user?.id ?? null; const options = { ...req.body, userId }; + + let isAutoBanned = false; + if (userId) { + isAutoBanned = await autoBanForNewAccountLinkComment({ + userId, + text: options.text, + content: options.content, + source: 'discussion', + }); + } + + if (isAutoBanned) { + throw new ForbiddenError(); + } + const newDiscussion = await createDiscussion(options); + return res.status(201).json(newDiscussion); }), ); @@ -72,10 +91,27 @@ router.post( if (!ok) { throw new BadRequestError(new Error('Please complete the verification and try again.')); } - const userId = (req.user?.id as string) || null; + + const userId: string | undefined | null = req.user?.id ?? null; const { altcha: _altcha, _honeypot, ...rest } = req.body; const options = { ...rest, userId }; + + let isAutoBanned = false; + if (userId) { + isAutoBanned = await autoBanForNewAccountLinkComment({ + userId, + text: options.text, + content: options.content, + source: 'discussion', + }); + } + + if (isAutoBanned) { + throw new ForbiddenError(); + } + const newDiscussion = await createDiscussion(options); + return res.status(201).json(newDiscussion); }), ); diff --git a/server/spamTag/commentSpam.ts b/server/spamTag/commentSpam.ts new file mode 100644 index 0000000000..2b82c8a333 --- /dev/null +++ b/server/spamTag/commentSpam.ts @@ -0,0 +1,159 @@ +import type { DocJson, NewAccountLinkCommentTriggerSource, UserSpamTagFields } from 'types'; + +import { type Mark, Node } from 'prosemirror-model'; + +import { editorSchema } from 'client/components/Editor'; +import { SpamTag, User } from 'server/models'; +import { contextFromUser, notify } from 'server/spamTag/notifications'; +import { upsertSpamTag } from 'server/spamTag/userQueries'; + +const DEFAULT_NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES = 10; + +const parsedWindowMinutes = parseInt( + process.env.NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES || + DEFAULT_NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES.toString(), + 10, +); + +const IS_WINDOW_MINUTES_VALID = Number.isFinite(parsedWindowMinutes) && parsedWindowMinutes > 0; + +const NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES = IS_WINDOW_MINUTES_VALID + ? parsedWindowMinutes + : DEFAULT_NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES; + +const NEW_ACCOUNT_LINK_COMMENT_WINDOW_MS = NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES * 60 * 1000; +const URL_REGEX = /\b(?:https?:\/\/|www\.)[^\s<]+/i; +const MAX_TRIGGER_VALUE_LENGTH = 500; + +type AutoBanNewAccountLinkCommentOptions = { + userId: string; + text: string; + content: DocJson; + source: NewAccountLinkCommentTriggerSource; +}; + +const extractUrlFromString = (value: string): string | null => { + if (!value) { + return null; + } + + const matchedUrl = value.match(URL_REGEX)?.[0]; + if (!matchedUrl) { + return null; + } + + return matchedUrl.slice(0, MAX_TRIGGER_VALUE_LENGTH); +}; + +const hasValidContentShape = (value: unknown): value is DocJson => { + if (!value || typeof value !== 'object') { + return false; + } + + const content = value as { type?: unknown }; + return typeof content.type === 'string'; +}; + +const extractFirstLinkFromContent = (content: DocJson): string | null => { + if (!hasValidContentShape(content)) { + return null; + } + + try { + const contentTree = Node.fromJSON(editorSchema, content); + const links: Mark[] = []; + + contentTree.descendants((node) => { + node.marks.forEach((mark) => { + if (mark.type.name === 'link') { + links.push(mark); + } + }); + }); + + const linkFromTree = links[0]?.attrs.href; + if (typeof linkFromTree !== 'string' || !linkFromTree.length) { + return null; + } + + return linkFromTree.slice(0, MAX_TRIGGER_VALUE_LENGTH); + } catch { + return null; + } +}; + +const getAccountAgeMs = (createdAt: Date | null | undefined): number => { + if (!(createdAt instanceof Date)) { + return Number.POSITIVE_INFINITY; + } + + return Date.now() - createdAt.getTime(); +}; + +const buildTriggerFields = ( + linkValue: string, + source: NewAccountLinkCommentTriggerSource, + accountAgeMs: number, +): UserSpamTagFields => { + return { + newAccountLinkCommentTriggers: [ + { + source, + value: linkValue, + accountAgeMinutes: Math.max(0, Math.floor(accountAgeMs / (60 * 1000))), + triggeredAt: new Date().toISOString(), + }, + ], + }; +}; + +export const autoBanForNewAccountLinkComment = async ( + options: AutoBanNewAccountLinkCommentOptions, +): Promise => { + const { userId, text, content, source } = options; + + const user = await User.findOne({ + where: { id: userId }, + include: [{ model: SpamTag, as: 'spamTag' }], + }); + + const accountAgeMs = getAccountAgeMs(user?.createdAt); + const shouldSkipAutoBan = !user || accountAgeMs > NEW_ACCOUNT_LINK_COMMENT_WINDOW_MS; + + if (shouldSkipAutoBan) { + return false; + } + + const linkFromTree = extractFirstLinkFromContent(content); + const linkFromText = extractUrlFromString(text); + + const firstLink = linkFromTree || linkFromText; + + if (!firstLink) { + return false; + } + + const previousStatus = user.spamTag?.status ?? null; + + const fields = buildTriggerFields(firstLink, source, accountAgeMs); + + const { spamTag, user: taggedUser } = await upsertSpamTag({ + userId, + status: 'confirmed-spam', + fields, + }); + + const shouldNotify = previousStatus !== 'confirmed-spam' && process.env.NODE_ENV !== 'test'; + + if (shouldNotify) { + await notify( + 'new-account-link-comment-ban', + contextFromUser(taggedUser, { + previousStatus, + spamFields: spamTag.fields as UserSpamTagFields, + }), + ); + } + + return true; +}; diff --git a/server/spamTag/notifications/index.ts b/server/spamTag/notifications/index.ts index a149fd4a2e..b89735bbc8 100644 --- a/server/spamTag/notifications/index.ts +++ b/server/spamTag/notifications/index.ts @@ -22,6 +22,7 @@ export type SpamEvent = | 'new-spam-tag' | 'suspicious-upload' | 'honeypot-ban' + | 'new-account-link-comment-ban' | 'manual-ban' | 'spam-lifted' | 'community-flag' @@ -96,6 +97,7 @@ type Contexts = { 'community-flag': CommunityFlagContext; 'community-flag-retracted': CommunityFlagRetractedContext; 'community-flag-resolved': CommunityFlagResolvedContext; + 'new-account-link-comment-ban': NewSpamTagContext; }; const handlers = { @@ -122,6 +124,18 @@ const handlers = { }), ], 'honeypot-ban': [(ctx) => sendSpamBanEmail({ toEmail: ctx.userEmail, userName: ctx.userName })], + 'new-account-link-comment-ban': [ + (ctx) => sendSpamBanEmail({ toEmail: ctx.userEmail, userName: ctx.userName }), + (ctx) => sendBanDevEmail({ userEmail: ctx.userEmail, userName: ctx.userName }), + (ctx) => + postToSlackAboutUserBan({ + userId: ctx.userId, + userName: ctx.userName, + userSlug: ctx.userSlug, + userAvatar: ctx.userAvatar, + reason: ctx.spamFields, + }), + ], 'manual-ban': [ (ctx) => postToSlackAboutUserBan({ diff --git a/server/spamTag/notifications/shared.ts b/server/spamTag/notifications/shared.ts index 7e4572d1b3..e1cb31b7e9 100644 --- a/server/spamTag/notifications/shared.ts +++ b/server/spamTag/notifications/shared.ts @@ -2,51 +2,103 @@ import type { UserSpamTagFields } from 'types/spam'; import { getSuperAdminTabUrl } from 'utils/superAdmin'; +const DEFAULT_NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES = 10; + export const getUserProfileUrl = (userSlug: string) => `https://www.pubpub.org/user/${userSlug}`; export const getSpamDashUrl = (userName: string) => `https://pubpub.org${getSuperAdminTabUrl('spamUsers')}?q=${encodeURIComponent(userName)}`; export const buildReasonText = (reason?: UserSpamTagFields): string => { - if (!reason) return ''; + if (!reason) { + return ''; + } + if (reason.manuallyMarkedBy?.length) { const last = reason.manuallyMarkedBy[reason.manuallyMarkedBy.length - 1]; + return `Manually marked by ${last.userName}`; } - if (reason.suspiciousFiles?.length) return 'Uploading suspicious files'; - if (reason.suspiciousComments?.length) return 'Posting suspicious comments'; + + if (reason.newAccountLinkCommentTriggers?.length) { + const last = + reason.newAccountLinkCommentTriggers[reason.newAccountLinkCommentTriggers.length - 1]; + + const sourceText = + last.source === 'discussion' ? 'discussion starter comment' : 'thread comment'; + + const accountAgeMinutes = + typeof last.accountAgeMinutes === 'number' + ? last.accountAgeMinutes + : DEFAULT_NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES; + + return `Posted a link in a ${sourceText} within ${accountAgeMinutes} minutes of signup`; + } + + if (reason.suspiciousFiles?.length) { + return 'Uploading suspicious files'; + } + + if (reason.suspiciousComments?.length) { + return 'Posting suspicious comments'; + } + if (reason.honeypotTriggers?.length) { const last = reason.honeypotTriggers[reason.honeypotTriggers.length - 1]; const parts: string[] = [last.honeypot]; - if (last.context?.communitySubdomain) + + if (last.context?.communitySubdomain) { parts.push(`community: ${last.context.communitySubdomain}`); - if (last.context?.pubSlug) parts.push(`pub: ${last.context.pubSlug}`); + } + + if (last.context?.pubSlug) { + parts.push(`pub: ${last.context.pubSlug}`); + } + return `Honeypot triggered (${parts.join(', ')})`; } + return ''; }; export const buildHoneypotContextLine = (reason?: UserSpamTagFields): string | null => { - if (!reason?.honeypotTriggers?.length) return null; + if (!reason?.honeypotTriggers?.length) { + return null; + } + const last = reason.honeypotTriggers[reason.honeypotTriggers.length - 1]; - if (!last.context) return null; + if (!last.context) { + return null; + } + const parts: string[] = []; + if (last.context.communitySubdomain) { const communityUrl = `https://${last.context.communitySubdomain}.pubpub.org`; + parts.push(`Community: <${communityUrl}|${last.context.communitySubdomain}>`); } + if (last.context.pubSlug && last.context.communitySubdomain) { const pubUrl = `https://${last.context.communitySubdomain}.pubpub.org/pub/${last.context.pubSlug}`; + parts.push(`Pub: <${pubUrl}|${last.context.pubSlug}>`); } else if (last.context.pubSlug) { parts.push(`Pub: ${last.context.pubSlug}`); } + if (last.context.content) { const truncated = last.context.content.length > 200 ? last.context.content.slice(0, 200) + '...' : last.context.content; + parts.push(`Content: ${truncated}`); } - return parts.length > 0 ? parts.join(' | ') : null; + + if (parts.length > 0) { + return parts.join(' | '); + } + + return null; }; diff --git a/server/spamTag/notifications/slack.ts b/server/spamTag/notifications/slack.ts index 267439bb0f..cb4cd56061 100644 --- a/server/spamTag/notifications/slack.ts +++ b/server/spamTag/notifications/slack.ts @@ -51,7 +51,10 @@ type UserBanSlackOptions = { }; export const postToSlackAboutUserBan = async (opts: UserBanSlackOptions) => { - if (process.env.NODE_ENV === 'test') return; + if (process.env.NODE_ENV === 'test') { + return; + } + const { userName, userSlug, userAvatar, reason, actorName } = opts; const profileUrl = getUserProfileUrl(userSlug); const dashUrl = getSpamDashUrl(userName); diff --git a/server/threadComment/__tests__/api.test.ts b/server/threadComment/__tests__/api.test.ts index f71b5f899c..67f83f8d7a 100644 --- a/server/threadComment/__tests__/api.test.ts +++ b/server/threadComment/__tests__/api.test.ts @@ -1,3 +1,4 @@ +import { SpamTag, User } from 'server/models'; import { expectCreatedActivityItem, login, modelize, setup, teardown } from 'stubstub'; const models = modelize` @@ -238,3 +239,30 @@ it('allows admins to edit users comments', async () => { .expect(200); expect(threadComment.text).toEqual("I eat bees. They're delicious"); }); + +it('bans new accounts that post thread comments with links', async () => { + const { guest, publicDiscussion, publicThread } = models; + const agent = await login(guest); + await agent + .post('/api/threadComment') + .send( + createThreadComment({ + discussion: publicDiscussion, + thread: publicThread, + text: 'Visit https://spam.example now', + }), + ) + .expect(403); + const user = await User.findOne({ + where: { id: guest.id }, + include: [{ model: SpamTag, as: 'spamTag' }], + }); + expect(user?.spamTag?.status).toEqual('confirmed-spam'); + const newAccountLinkCommentTriggers = (user?.spamTag?.fields as any) + ?.newAccountLinkCommentTriggers; + expect(newAccountLinkCommentTriggers?.length).toEqual(1); + expect(newAccountLinkCommentTriggers?.[0]).toMatchObject({ + source: 'thread-comment', + value: 'https://spam.example', + }); +}); diff --git a/server/threadComment/api.ts b/server/threadComment/api.ts index f74f3228b6..df23e44a64 100644 --- a/server/threadComment/api.ts +++ b/server/threadComment/api.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; -import { isUserBannedInCommunity } from 'server/communityBan/queries'; +import { autoBanForNewAccountLinkComment } from 'server/spamTag/commentSpam'; import { verifyCaptchaPayload } from 'server/utils/captcha'; import { BadRequestError, ForbiddenError } from 'server/utils/errors'; import { handleHoneypotTriggered, isHoneypotFilled } from 'server/utils/honeypot'; @@ -13,6 +13,7 @@ export const router = Router(); const getRequestIds = (req) => { const user = req.user || {}; + return { userId: user.id, parentId: req.body.parentId, @@ -29,19 +30,33 @@ router.post( '/api/threadComment', wrap(async (req, res) => { const requestIds = getRequestIds(req); + const userId = req.user?.id ?? null; + const permissions = await getPermissions(requestIds); - if (!permissions.create) { + + const canCreateComment = !!permissions.create; + if (!canCreateComment) { throw new ForbiddenError(); } - const userId = (req.user?.id as string) || null; - if (userId && req.body.communityId) { - const banned = await isUserBannedInCommunity(userId, req.body.communityId); - if (banned) { - throw new ForbiddenError(); - } - } + const options = { ...req.body, userId }; + + let isAutoBanned = false; + if (userId) { + isAutoBanned = await autoBanForNewAccountLinkComment({ + userId, + text: options.text, + content: options.content, + source: 'thread-comment', + }); + } + + if (isAutoBanned) { + throw new ForbiddenError(); + } + const newThreadComment = await createThreadComment(options); + return res.status(201).json(newThreadComment); }), ); @@ -50,17 +65,16 @@ router.post( '/api/threadComment/fromForm', wrap(async (req, res) => { const requestIds = getRequestIds(req); + + const userId = req.user?.id ?? null; + const permissions = await getPermissions(requestIds); - if (!permissions.create) { + + const canCreateComment = !!permissions.create; + if (!canCreateComment) { throw new ForbiddenError(); } - const formUserId = (req.user?.id as string) || null; - if (formUserId && req.body.communityId) { - const banned = await isUserBannedInCommunity(formUserId, req.body.communityId); - if (banned) { - throw new ForbiddenError(); - } - } + if (isHoneypotFilled(req.body)) { if (req.user?.id) await handleHoneypotTriggered( @@ -82,10 +96,26 @@ router.post( if (!ok) { throw new BadRequestError(new Error('Please complete the verification and try again.')); } - const userId = (req.user?.id as string) || null; + const { altcha: _altcha, _honeypot, ...rest } = req.body; const options = { ...rest, userId }; + + let isAutoBanned = false; + if (userId) { + isAutoBanned = await autoBanForNewAccountLinkComment({ + userId, + text: options.text, + content: options.content, + source: 'thread-comment', + }); + } + + if (isAutoBanned) { + throw new ForbiddenError(); + } + const newThreadComment = await createThreadComment(options); + return res.status(201).json(newThreadComment); }), ); diff --git a/types/spam.ts b/types/spam.ts index 9830621fdc..e27b861947 100644 --- a/types/spam.ts +++ b/types/spam.ts @@ -149,9 +149,19 @@ export type SerializedCommunityBan = { /** @deprecated use SerializedCommunityBan */ export type SerializedUserCommunityFlag = SerializedCommunityBan; +export type NewAccountLinkCommentTriggerSource = 'discussion' | 'thread-comment'; + +export type NewAccountLinkCommentTrigger = { + source: NewAccountLinkCommentTriggerSource; + value: string; + accountAgeMinutes: number; + triggeredAt?: string; +}; + export type UserSpamTagFields = { suspiciousFiles?: string[]; suspiciousComments?: string[]; + newAccountLinkCommentTriggers?: NewAccountLinkCommentTrigger[]; honeypotTriggers?: { honeypot: HoneypotTrigger; value: string;