diff --git a/infra/.env.dev.enc b/infra/.env.dev.enc index 11bb2fb24f..30595f8676 100644 --- a/infra/.env.dev.enc +++ b/infra/.env.dev.enc @@ -1,60 +1,61 @@ -AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:QTHQKsrGXVcC6n0Df+FPitm4spVEFmor8tBW1Us4KecRHT/CS/c4liG/zhmxg608o1BImvYUoNXOnAUzx0c7rA==,iv:UyRQD8CY/wKgBvfVwT9A6KME2OS8qr/DaFByVw2hy40=,tag:tEAiJg8C3RQFzVbl/kof0A==,type:str] -ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:pEQuEORnajXVGVKBeGIybmceHBr94su8UjdRdxVDs/w5P2lA+AOkljqmf58pFp4QYljvb8WM0K0Qucu6BX6nsg==,iv:5JKeF6ZlnlL9QKtSZQvSA8owri690+LfqdjO8qH9h0k=,tag:hYnfaZdz2U1NZrOyGbAmRg==,type:str] -AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:Zh6nZj9vyGdL7YYyjZnV1Hu2fsk=,iv:vIN6uPJMx0+BDGcHe3tazIOwZdzeqYSznyxDWgPE7yU=,tag:AkTJteLfaO55PmCpFdDHGQ==,type:str] -AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:AukGF5oUW76exk8tlVSCK8C4EbY=,iv:uYhLhWI5MmLLYX+0tE7b6JLSUmVgfV2/M/Rc2dbJeO4=,tag:a0vAFyRyyb926Oq1UMIGaQ==,type:str] -AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:uM/KzblBwrJX9ixFEk3thYP2x/c2pn+GHU0SfkbvbNUo6bJQKPHUtw==,iv:Kl9+6SMhzqd0/FepOET/5wOlmFHG0NSl40hZ+xpc2cw=,tag:ce4G5Wj8IhLtqGH9j4yOgA==,type:str] -AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:3yhIGaVfcSx82Iu570lGQTj7wg6/U4eKLJBX3fWllFUXPQ7YTaTSxg==,iv:Zw789TR9JYE8Zub372k1+nUUHHp5898+leNGmUUadxQ=,tag:OdHy7ixCn9HgAcyOotFf1A==,type:str] -BACKUPS_SECRET=ENC[AES256_GCM,data:vW/KL6d2JrTLEqMyWdewdG5arNFi/k4XItSJIpKtLCubWtVPA7Vx+ndKafk=,iv:A08RonZOgfK5Rv+jFCrPulB5GLFtPWQhzWEo7qVI0H8=,tag:YRMdEGEXtHwbXYHOxGb2IQ==,type:str] -CLOUDFLARE_ANALYTICS_API_TOKEN=ENC[AES256_GCM,data:2ycCWIKjallqDhI3tI7Y3DkJD64i6PpwTUkb+mTcFiho5W53mCjqX7LHoBQ/KM6//aHN7f8=,iv:14R0jm2nxMCd1pfRDah2n1b807opRio8/1oMqG6CBXc=,tag:uOH4SQRvgkW5wumxqQ1RfA==,type:str] -CLOUDFLARE_CUSTOM_HOSTNAME_API_TOKEN=ENC[AES256_GCM,data:aQjJLeWn2p0K5aMlGQezyhhnuvp8zIKCSdEzQRPq5y3vq5cRdrSijdLNl5PyFbyse3OdKW0=,iv:cY4t9ygDSouRuebY5sFQnOsFmMHD+STqiI5A7DOxpQw=,tag:CBEsbEuvR5sTy6iSboIfXQ==,type:str] -CLOUDFLARE_ZONE_TAG=ENC[AES256_GCM,data:G8HYYAD4o/9v2ewmQHLoyi7Gs/IC+rRfVbtrO7WG9lo=,iv:UU5q1PeCYI685vP0M0mPnfvUg1jEaJF29+n65YMGrms=,tag:PzupiZcYg+S60keNcbZscw==,type:str] -CONTENT_SEARCH_TERMS=ENC[AES256_GCM,data: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,iv:mRgRYJVuUOeYwrCZbjZIVZzjNuWpTsLkNYpl0j/wZNE=,tag:kOtCOlJB3gKyzaZsUo1Y9A==,type:str] -DATABASE_URL=ENC[AES256_GCM,data:oEBTHXU0LJ4AmF9ProfQDon5aGG4vDQK5JIC/o7OENh6Od9I/zRMaxOvyPM=,iv:EeYD+Z829jA7mGKL0HUDoMBbMTpxp2IaDm+Z+Ik98K0=,tag:NtmCFVY4OCmc73dKlWvtHQ==,type:str] -DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:4OWiB4JXhX2j/yk8YF//3yYLZpG2RC34yUJUeBi9ilNySQ==,iv:2TPp76R7IK2LxrFPTv1BbYIYEEf9oyZbY9fODp8negY=,tag:ei3JiVgIS44q06fvPIPioQ==,type:str] -DOI_LOGIN_ID=ENC[AES256_GCM,data:dBNBTJAj,iv:+L9bHQ0qpE30YIvkHhLy0F94xk4WltCQ0kiN1tm5MH8=,tag:42lv4Qc61GMca9SU22yPaQ==,type:str] -DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:pYL86VNuswtQyo5VTmDSBO8FWbo=,iv:eyDVpD/d9R/YqUDiAN823aRtWJSEIx71aZ5vzpSxMTo=,tag:3dWa2DwrxdeYfYxL4G84hA==,type:str] -DOI_SUBMISSION_URL=ENC[AES256_GCM,data:tUIkPyvU2TE3cWaGgDf+AFgzFgDibsgUUV2hNkdDvJxGYsAecNaq34o=,iv:SoWYYFQaI78/4KdwSu3Q70vYsTawiwv3rHDCPAN+J0g=,tag:u+4BZU0agtSkFHBPF3G76Q==,type:str] -FASTLY_PURGE_TOKEN=ENC[AES256_GCM,data:w24gixo2dL6Nly9Numyq79W1FkC7gog5QxIwb7r1iJw=,iv:NJXaDOiofZwIHtuFaFbAc1S/A7wsZURUt5DD89lvJIc=,tag:C4hoW3wSrcEFXrapr5UVQg==,type:str] -FASTLY_SERVICE_ID=ENC[AES256_GCM,data:km/VXm/CCP2VUJFkdrh/G/tr+A8VbA==,iv:x9vrwMvPg4eXUQB3MuzZ9Ra5jD3y4hJYHGl2vTWmyys=,tag:rXPz7yyBL1i7g3BNe14xbg==,type:str] -FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data: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,iv:t/EvVAQw2gbV7qwOZO+MlmKqCETbC7gqRsXrKxDvWUk=,tag:g68huzvs+cmz/jNKj786IQ==,type:str] -IS_DUQDUQ=ENC[AES256_GCM,data:+obHZg==,iv:L92l1JcMlAf3eBgrmn5ktSkRWAu80OsM25pWAwbCGz4=,tag:mgSQTM2cjEyoG5tVwqQQIw==,type:str] -JWT_SIGNING_SECRET=ENC[AES256_GCM,data:dkLpNzbugrM6XUEjI9PbmXqVDMB41fbL0BRCZ5Wh1/cnXqpAZg9X1+ql1qIAWl4vUdTT0Qla5hBvQS9AcTl2VrCsu3opJgZ9KfooMnO6fgeIcKn2jolWWOXgafKZ9OauXHUCCAyhZK2MHz7kY2NcaJHjqdE+gzec0BW4s+T+44iKeX9lWCueGD0Z0pomAfJCHVh5TOppxNase4rth48Fpl0b+jbIpA9puXcFSHV4xfPPnDlo3zeO012HdTf28QWOT7hwnw5aTBDKyqFoUNoJ/wONtzYpkMoiuYAWJT8iamrCBSJP5yuQfnQHHBxlx8DVqN2sB598XkvvBRJTjL8c4qU/9sKQK+SeX8OiJ6b7oIr6tnBuHGtmHy/atJqCTlABv083gLA1Yvsl7oI+3XZkqWcuT1JmsJzM5IhfrrcgY66qVAfQtBwd7SLB/sX9286n62FCLu+sy+otl4Tc4l/Cbm9Eslp+LV+XD/XvixqSnrH1tVE6WZv+t0LM6GA6UALm9C0kP+WFqu91/q1hK5WYXTFpeOCy8t1u+ORQUABQf5HtJMxgsk9kDyKO8IlQlLs63szsa3kERJbQyy3UEKJ80Uywhkgz6MDF3U1QbJEfGxgq7wInl4nGFLe9Dso61ULzUHOZD+03JcwS1cVpHXJO+2FsLs+diiV16XqNxUu26YFu/cbCc2/0mbrJoFF7KnrW2e8s2nzdBsWh0qj0A1mNWmhEC7HkmRaqkajhGR5Mqgp94P4/Aoz/BIJoiCXOk+LF8GpodrghGSVDsJBGD6/2om385LE218tCnmShzI8IBT8oRh7IXnTKmZX5Pi1dxD3GG6wjtFL5ecxNRlVPZITCEbj2sIN+HaweqP8rzgufrO+Qbn6uySR5zjAsvTZt1QRsn7m9nLFHy5UzZbrpIxt4x00x14oUpTBnDhakm5OYRkc7Sk4o40mO1ibSMdXBCRMiAs9Wwlw6DfeBxF2zbbNGX3T6A8TsNuZLhQIPhol0KKNNhrIeozqi7w2gmJjTlJQVttg0fin8KFI9cwKlhcuFQknO3bzB5v7RxZEg6PdWQvS3L3f9uuISwgFS8sV8IloXIlmJwqDxE/g8bhRysdj1XHLxvSxd4VNex323H7Uw1h+6U2Pqufa4JDbcOUl8a58DJE69xNs+9a0vKhI6sghAe8fq682BNM0kiV5etoT4AHwr61VVnT43okoUFWBfYRwnWhwn0kDZ2N/Tc6zIF26FRXqKRS/WKNI4KBN51tVRCX73Y9BReSEMAHwz64A4wnvn32orT2ICejTkauSawFGOcBB80kws3zMCcHkcueu+5aZL4687N9h2UpAu1S+JEwE1HGRTb1PP9SHE+/dr3+yVig==,iv:bepSFYamCtmRhGMhoMUmEvKcwGX8KG6bCPlU0fE6dsU=,tag:9by0PjYZ9GZIpja/XPzHYg==,type:str] -MAILCHIMP_API_KEY=ENC[AES256_GCM,data:OSemiKy5JLCj8q3cB6MqPbDe+BJv46zR3Pjh59l4qTTt4/9W,iv:FQ1aBZDU26e9pVwiHjoxit4h88EWYSFF0YS3/jE6edY=,tag:Eg9BksR/m7a6UCDFxnSfCg==,type:str] -MAILGUN_API_KEY=ENC[AES256_GCM,data:vmeClID/tuJeMKhAEBqGuUlKVmoRZk4XH80faSFBSkfoJqX3,iv:ueEV3T3tD1DEgti4MXQLgEohKzgqMwHKK5jCMt+xlJg=,tag:o8++Leq8zn0yESoS2w+GzQ==,type:str] -NODE_ENV=ENC[AES256_GCM,data:5sqC5U2w3gs9bA==,iv:fmfMUpFPGfIt0X6ZAbm4j4oH2pCiRYy7OG66eb7C7EU=,tag:E9fgASNvznjqbzjKMn3VWw==,type:str] -S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:D2H1silMP93AZI/N+rIR2iSkE9E=,iv:lmMAB7dcHhFyS/nxjCBtBJrrH3NIrmg+GiO/ba7NmjI=,tag:QQ2KHknsdIisnhgKDrL4Xw==,type:str] -S3_BACKUP_BUCKET=ENC[AES256_GCM,data:l+WkrTk4NsH/Rfc=,iv:fkdyvBn//ULtid63U/CKTXgpx70bk46QMQ4sOBZzdnw=,tag:eOkieRCMvwymWm+uRnpTaw==,type:str] -S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:yOdkAwO+XStgzkwo8Nt5RSDU96JexzeU2UwMpORgzNLQXm4=,iv:kw2k3EedL5bjVbCL6CEHY/F0aSNg0lHAKUaCb3EzGyc=,tag:sKwXq+SD3+4O/a4rs3PgIw==,type:str] -S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:/kFd13/ExfcwFX4/zcQSQ0j5E/9M0avGQluhl6I00lXS+eJz/qVg8A==,iv:kyJaxXyk9cAXFNeATBjMqC0yEvI3mGwD49a+/q9tUPY=,tag:pYuabKR84BpiYYPyGhoc8w==,type:str] -SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:kXbKKC5rK0JNyp4YXOk1IObQEsDjdbg7lt5l/lKQzfxHi982e25Ux5kTY59xp2SnDyNNVQZaFa5qhQGKG5fQBKDL6NNir81f9hdIimLaPr0f/Z7zw8Lx2uZoOXwf0gSRIp3E8tnNj0aj009miOp9zfd/gHUeSwPXdF2bKxu6SMbSOXoK7G89w8gTLtuKdcoptqIGYAWlUYOKmYiDY7XewRp0vil1skaom6Y+6k+t3rbr3L0a9Q+Cc3pxDQ==,iv:ZiX210v2BthDmlh0wXLydYbj0GzBY/fb7VtahLt46+k=,tag:+2DVZo9oxBFojHtEbFXUIg==,type:str] -SENTRY_ORG=ENC[AES256_GCM,data:9rhL,iv:qWrrpZLPsBNiV85XtjY0MCj4nY3jlptAFmjxiWAXQeA=,tag:7gh4OpcrMGWeRyeLsZ8ztw==,type:str] -SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:azQ=,iv:aqInEL2yeXtDwZPL4oovJhvvKDS1VohqCfKxJhijWcg=,tag:u2xR+O3Gh4Sl+/SBqJzwUQ==,type:str] -SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:XzGfApMoNtWvpoUef/NlC4P6ms9FMCRnMHNs95ZBk89ht1sDOlBCdtRmt2/Kzv4SQA4oTDRA4J357AGZKP8L/UeWswBHB1QeFnz9GvZE3w==,iv:XNrtFa0gGgGcFcyMBxKDF/8tJpRSdJ5Zqi+l3m6M8TQ=,tag:zJrK07YBxmc0X4bfAUoDhQ==,type:str] -SMTP_HOST=ENC[AES256_GCM,data:GJLUyrkiEl4zPyTj6ZxNCKPZaA1aIhMOlR4vJ7fohSrYMw==,iv:aRD1It5hgjVSIMEbtXOJs8/pUaXHsQ063Zfko7Z6+C8=,tag:jl1t5KiG3ftueSdHyQzkwA==,type:str] -SMTP_PASS=ENC[AES256_GCM,data:+pnmEDvbXpNLpnroMv5FD2Y4otwjTk3k2JX82+ve2xIs9dzKMDkVPXkXcqo=,iv:cF/29JYKF+IwGRAWZzLuDt0+ZxJ3K/eegMr8XHG4GDY=,tag:/932F/VShBTzjBR03TPMbw==,type:str] -SMTP_USER=ENC[AES256_GCM,data:FyH5lsmBv5KleZlUM060W11YqeM=,iv:3xr6bPbG4pIW6Jc/pnuP2RAtl94JBYUJ2QdwOsE0mnM=,tag:zOkkt4HVcKjiVQNfp2IqyA==,type:str] -ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:TbcRcUKMSbnh4uZa6eMMzwTGVbc=,iv:zP1yYWFNh2W4d7+IP8v9ut+qTmgZ2LNNa7YzALXKOzE=,tag:LRKOtZYEvuelCYU7m6/kXQ==,type:str] -ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:AuqTkMUytxv42YlsARXnGr5lkXE=,iv:xZdJ26k0WSfwGdkxsLLrpy8vYzYQRPM3edhksMSGOUo=,tag:v8YJYUqGIinUGRr4ITA5cQ==,type:str] -#ENC[AES256_GCM,data:5UNnOoaCSXve3FQuWEeMQTU/bvg=,iv:TvRWMmfiSIgZu1E/H271RZg7t5ZXZuS00ZWUZNZuHU8=,tag:Wy+4V2xZWRQ/p8YRR9fBUw==,type:comment] -OIDC_ISSUER_URL=ENC[AES256_GCM,data:KD3dcG0IBxI65gS9zn0zU2OyqH7XDLaUjF97NBtg65XQSP9LmA==,iv:Rgr2YOSprfARpIclEz1vnvv9d5n02ICtXILisV98qSc=,tag:jIh/cOn4gxP+u/9GsGLgDQ==,type:str] -OIDC_CLIENT_ID=ENC[AES256_GCM,data:d6wnR+55BHfe,iv:y2qsuRl8+74N6CreatAlEnmezfTRPvOuRdaLF2H3Vy8=,tag:wpsl8Oo9oPJD0KkerDwsCA==,type:str] -OIDC_CLIENT_SECRET=ENC[AES256_GCM,data:h7rW7LyWb92196d7KvJ7gQLMJAnTwNw9qV1mmnyU2qwUXottErv463JD/87Roc2NT/VPVrs5lNcTGEMF1uikaQ==,iv:Q4/I1SPV41YqYoH2LSpcThgb89jcj08oebatpmKzOBU=,tag:ef8yNKjrJCpgyklDhY2h2g==,type:str] -AUTH_INTERNAL_API_KEY=ENC[AES256_GCM,data:oDMLpeLW5AjUPjzQmwb59NA6ULq8YdLraJLeuKR5WK6yBTZt4OKImnqQnmYXCN59O5YCrqmNFVJDci18N9BQYQ==,iv:dGYxwjgQn5iomGFldVMWnJpfxLtyQkwazDO+fBVK2X0=,tag:OZjvP9v87af9Ubphi1s2WQ==,type:str] -OIDC_ACCOUNT_URL=ENC[AES256_GCM,data:7Fj4JuBQ130186MMlgURKoCGijYwDASqAjISd+hnoQBajNuxXuLOBg==,iv:0O50QSvdldSESMoBNZyagGz8QYUkip7QqiZkcwuAku8=,tag:WZSTC+XX85vPKmWD4i5jSg==,type:str] -APP_URL=ENC[AES256_GCM,data:/x8aPCCcsslp6gD7MwA5IC9WO8tAHg==,iv:MIBAmZCLD21QI4CsDWkyTIuSfsY4BhlFRRQ+lI/7/Zo=,tag:UNR22KrCQdSpMsWWPzXI+Q==,type:str] -sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjSmZoSHREN3NVMXdFNzRv\nRmllOGNYUExHRGFXamR3dE9yb3ZJYUsyaWo4CmtQYjBmL0ZpSkdtL0ZKUS9ya1gz\nN21keVZTeTNFbnFzbXhZM2N6Z2xXTk0KLS0tIHV4bklFRWdvMVBIdkpyd1VxYnpL\nNVB0SUZ3aTJvYnlzRUpIYURLRlM1aWcK6Vpqr6F+Fa2jO9ndX5OeXoe8Mgg9KBPa\nt196Mw3nG5v+/9m4iH24/Aip7rR2USnuQ2NWZ18NqdBgb2cstLOWaQ==\n-----END AGE ENCRYPTED FILE-----\n +AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:h7qbTJxJeUHu8b1cfCrCBK8M/LJfaxEozxdQVILgr3tb4VggkzsPpbr4KNOtK8pRBDXft4dxfdvTTcckk/KzwQ==,iv:Qv5WoB8JJ44uNf44/Zhbn9NamsM4b3zBCYesDM16BwE=,tag:LlxtNGy64+eVqsf0/RKqcw==,type:str] +ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:wdeZ4XbAsrqx+7K/LKXj5oeco1Mx4P/PAKeYMuOgJXyrd6G6kuy0vnJkrCr/0NpqIybvQhT6hi9C0mxkL2rm1g==,iv:kI4o3TaKl5vGzQe1qypmMXCuxO5NnuWsVh3/n1PU4x8=,tag:aBmIjqFdB+MtW/BZifh5RQ==,type:str] +AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:j5xHwp86kVe+Q43O2nM4mI9PqEU=,iv:E1rhuegAEZMFwgLJi1wlq8Sl0SsCxZL5BvgZK9lfBpE=,tag:ZI82fECFJ77UyXMPcLFp5w==,type:str] +AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:QUJkXAnMIbLkb07T1zekSQRX8sc=,iv:gUkgc1oU1rPHUXQrhj58qxkfde0jJdmQxBTZs5u/6bM=,tag:QJmtOzeH67JVn5tr4PHEiQ==,type:str] +AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:eu7hz2BeK5ww+90nphpbFB2rxQs/hAgGAQZVMioDvqFymeoAJuaN7Q==,iv:AVpEozYwF0tQqv7suBwuvC6d+e5n1GUXp85xutajZ78=,tag:/3cIpBaVHWMTIHxMHKpSeQ==,type:str] +AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:nIwH+UU2+F5l9047iQPRkEqB7A2h4mMFYKfem66L6uDKoouvKV9BWA==,iv:60GYLILKK11erR1eVLgW1H4NNiAligZaE9D1tSLd9jg=,tag:EH7sgJR2vkLZlCY51wnBBQ==,type:str] +BACKUPS_SECRET=ENC[AES256_GCM,data:5sQqL/w7ZpDC122QJCSumSDjh4bPSq5wVAvZXs2qI67dVKvBHeDoMZdyFr0=,iv:Z3NwyZH1tDQTeys+YnR5yt89FQ5yeKTong0JsC5Ek2Q=,tag:Tiezth3nfwje7jSH73V3lA==,type:str] +CLOUDFLARE_ANALYTICS_API_TOKEN=ENC[AES256_GCM,data:Rlm1/xO2Brfw/Ori0ERKtRhuvt4ljMh8p2RzO9nUDQUEwcLtHJ2LqcZxqq/xyuQXIJ61grw=,iv:FMnKOZDde8L90W+7nN/yG5sbLYppVWYv0c33py04ubc=,tag:T2V5DmNP1iazPxQjNd3A+w==,type:str] +CLOUDFLARE_CUSTOM_HOSTNAME_API_TOKEN=ENC[AES256_GCM,data:g6kJke1ZjaaxB/yY2PF+B1yrL5SKOoUIxFuE3t2K+RCQtI96e8EjAluI8/IzbG3dYzOsQFs=,iv:PuIHMwELLVGzv3/znFe/qs4HPgoc1sED7yvsW5DbbwA=,tag:Jqy/VfP9KePPf3KQpzw8IA==,type:str] +CLOUDFLARE_ZONE_TAG=ENC[AES256_GCM,data:uCGuHryb2PlYtRHkQUwrm7EPf75JRBXh4KWj6iiHqcs=,iv:udBUrPTyMntEluWHwp+iKLmLt1RqXoUOXGQg4sg7a6E=,tag:0dgxRDzYHjXS4rETNFocBw==,type:str] +CONTENT_SEARCH_TERMS=ENC[AES256_GCM,data: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,iv:mwYtebAqKsnihje7S67mrm5iXokE8xUKe5Oc/0RJ9rg=,tag:40SWkzDbjXDvaumVHofFSw==,type:str] +DATABASE_URL=ENC[AES256_GCM,data:I1XJzlgkaK8+vzwXOlPxAS4KCpxlh9di1cB+PjowKgNE9S2B2QnXwKRERMw=,iv:ZTd+wHr9D6S0l9J6quPkMDepZFc2Tq5r1g2Z79eFtA8=,tag:UZBDsm2jEaTYn4jhZpwX2A==,type:str] +DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:V5UsSaEeBwniXO7gcuZgRkGBzQS+wXTHzz8SqV2FDLvhPA==,iv:nCZkem7NJcJF4AYorqTtRh0WRx6kmccxojGfhj+wd9c=,tag:PQBxwom9tFR0BsuHLQXMyw==,type:str] +DOI_LOGIN_ID=ENC[AES256_GCM,data:aNSNmRff,iv:Iq+j9h+N5H0JGZ99Rk4I50opWPgAlCAwkMgXzNHVId8=,tag:bjtqMU2Ng6iu9TjlfJ1Exw==,type:str] +DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:7O636rpkjtDE09mcsBTNFD4HtiE=,iv:7wTPpEaTGyV6J2NGFmQMqaSgMT24qSIs/TP9waArXWs=,tag:KRdUZT+IjFHbXIDy7YZhTg==,type:str] +DOI_SUBMISSION_URL=ENC[AES256_GCM,data:eIo9vFwqznuI/2zDZv/8P9CMWg0XvNVebycPYaM/xVdxmfj3ASUqMTY=,iv:i0FWp1P4GUCTJEziwBV90VS518otmu7ojvmbV7HdA7s=,tag:8iM8GU4bwGQxDVdIiZP1yQ==,type:str] +FASTLY_PURGE_TOKEN=ENC[AES256_GCM,data:BTg92mvw6xmYQHpFlqLbtHFO7QeL5ayJgaqo71Jlr1A=,iv:lzr1hhomKMx9q+K7uDnuFr9W4mJFMHkG2sBj2+wi+80=,tag:o0wm6ws9zkC/RjX/aMjDvQ==,type:str] +FASTLY_SERVICE_ID=ENC[AES256_GCM,data:LmtEdR7CieGtOFPGkIYSNvoHj/aM9Q==,iv:ORwDwVXHMCCQ82AwNlRHICkCAXzW00ckMET8wlUjkFo=,tag:b23qbLhlm9zBBV2dB0u+xg==,type:str] +FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data: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,iv:d/IlvuqRqxjxgUXyHE71+qsi3brjh8M7y6W+xvGe9No=,tag:r9fzNRKVxrwtEY1chk1smw==,type:str] +IS_DUQDUQ=ENC[AES256_GCM,data:pGhSBw==,iv:88vE4NAY3P9UtI4Jal9TzFgfc90J3r0VDvLR8Dj9PxM=,tag:vJm3ej/3DKZXa7KUVgJdmA==,type:str] +JWT_SIGNING_SECRET=ENC[AES256_GCM,data:F47NxQuvKoO9/Ylu9KpFmlSxzGdRcjdn5EiBSDwStYidyPdYqGJsr44nUtOvCpIEZR1NnCAbccGtJlUgdxkYKRA0WqBVeQhkgA2DWN6J2Gwt8hFLrJJ0981USz+nTNiEjalmN8ebwOKmm6Zu25zL6kOUZI+nndeW9QBFW2ce1PLi3TXc4GrTrJrRDdOXHiCSpUeDmKxC0MM0Ieai9DvBURQL8LrfHDkCx5mgFO7E3o55aS82MZngdpqT3zwBgC++gbpXI//PV6Dql0RqM1ffHUtPxye+bDvvjFzTrbRnSOtCa8OGmhZO5be1notI+gGZVNPyc4x9g+VzFwgZa6VUNr5s+1JCpvSwsttYscXIB82OTMso3XIbiYIxH886/V2Y+kxlzS37sXrebDF+ptjjFAZc3VPpFERWeR1TuMZCFn+OSyvPfpMKO33f9NGOnYAs+UnVOeuemW3QnM4XvOTl+4+Ln8HHN5Lc1spJGnmGdLVkeJhwYOVyvsgMrY5TbN56DHqz9D2eSqiZ1KPM4i2ElGMA7OJ2P0BoUd9YXpUrx9SWcY7UFuwpgURr9uNrORK83RI07o7sFlwFM2/qBKz2D3LX9Jugx29z+P1CNj3q/209NM8sneNBaz5TgNoYJ6nm7+F6/krBmIeoB6Jp9YPeLLA6vk8rEFjm6ezwcpkCIYbzVfWZcojxlLF1IKPu5uLPxrzoV4k5ev2fo9Sya8x0mxPOEm30u2dSw5o2FDJjQmx3QCulpWIYlMZXUNE8ZeN3Ugh2AWpEqGfEDG5OaUXytKYHAmJ7aSJN8DyM/TJlgiLMssNGT/LGT3Zff+CTOBLI3d0nD/3g5yL1zdk1V4SdJp95inMJaywZ3cK6iJubaqicFe7ymqlJgglVjcwbWOsQB1rR+LU6ImWY+20ZmudVCJfBgvOY0kXE/zahG6dyr4Vxicj06NYg4IFu4faNVWLN/G6M4hEL1zqwbsoi+y3Ar0Pf2olPrr6jqGbcZRvUd0QtlWr5mP0kwJ+kSmOj+6qoVAF/WziWPEmZJwBYLPJEqXZUKOygAoxVU2NpbAzDR12muUyATEdTSDOilF7jaJ/epQDk6gOfBoptUcp1h9tGEx6ZBO+waOGJSmZpt0qMqsJg4hELfFdzOFnlDgAOiodEV9iU8HqXE4w90z2FxXmuNpfIg5AhgeO96tm3X6CIxanawvc/XWioal7N/7JZd/ZAxsNnqRsx/TU/TtTalinrJvWcfFzLrcPIwU3uWr8MCsVJWiFcE75J0CZBDizc7VlakDykjLD2h7xuDvH+4+mI3ENIALb/Q4/mTUaz0eW3LZdC67YULiCc5Ap3tBbCT8yTbJGrV7Ur7AiRkwum5ffrVA==,iv:NCxgW7WAv5AggPhBC+Fw/r2Yuu+7ByrQ8j1qxKhSPg4=,tag:Je7/Of8STALswBOTnXSn7w==,type:str] +MAILCHIMP_API_KEY=ENC[AES256_GCM,data:ftsngh2Qpdrs1JLDSXfWqRl96Ch6yhFxXBfuOhHyM+tslyXm,iv:Ej+WO4Tr60wcykHyzhMa0nPeD5woOkLFO5WvGJ/4/DM=,tag:vVCzLVzOt4QD7twvUOuq5w==,type:str] +MAILGUN_API_KEY=ENC[AES256_GCM,data:mz9UnNUJs9cDYHkZVUyXl4a5MCL7Xn77ZJ+ZD/SLjU5VjF6q,iv:4dWbkQd8cgCd9hTBySyeHaMhUPsOQm0Ze7xvdfiGO0g=,tag:VsXL3xVWnHe/fiWMyVgr9w==,type:str] +NODE_ENV=ENC[AES256_GCM,data:TtZv0z18OJO89A==,iv:QpcprV2W9l9kttjA+smPgo5xu1ENopcMJnwJEwkCl+4=,tag:uXFoaihKBLpZCFEI1paqdg==,type:str] +S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:tx87aZS1vv+I/hBUkPybzDkjA3A=,iv:IlYOJwByvJIS7vc/BTd0wt/HTFs/BbVM9X6Jo1g/qQY=,tag:UJuHx1XgeKSorMVY1BwpNA==,type:str] +S3_BACKUP_BUCKET=ENC[AES256_GCM,data:I5nxBWNEkxFLkPA=,iv:O8J67Ekfi0N1hf1NrcJVghPvko+kYFucjTMICtLVWAw=,tag:1Q3pJlDN3ls6OHlBfoLiMg==,type:str] +S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:TJAUdaPjFETxSUfxllGZSwnOwNOpdlUoRapJJpVywnDSCL8=,iv:ZnQQcvv2L9JMQQh9SJMmEQYRYtcRGVz7VOq01gWDmgc=,tag:FwPrlOCS3f+KcLfN6KepbQ==,type:str] +S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:iqtDRv9nwW0dBzRZV+sDnOfpec6v6I41xGJwu4eNZh2dvAfTi36LRA==,iv:EGtyqD/J0vq6hWejFUvHSPxyGCLn2ge0W8aFl179W/0=,tag:G4xp6MIfm6S/hSYf96CL9w==,type:str] +SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:ywVghraC+mTNLZw1IYutAjpgWqWfV8fNSibYxLGuXAKspdM/tM6RAMf+de9G1+NwQK64+aqdRuBOXIsHndDI7ppQPksJXfrSCBXnz5V+KE7ulIq9gK27jnLJZz7AefXZ/iRdsDCM6ebsO78obWhVULrYghM/5lENUSsMY6PwRbwyyqiiRkPG7Rf3CiEFpCrAx57/dvCb+Lqi/Odhtu5tQym2eJZnve6AXFL2anxiuymeR5n9eNDrBx7+qg==,iv:k9ty58qA8NLOPYeDrRaed6PaN7yz7bQanDpeCY1U79M=,tag:qe7g2mGO9lG6uQPTkvaWLg==,type:str] +SENTRY_ORG=ENC[AES256_GCM,data:karx,iv:rOJAiUiXF9JqruqfkkT5+piujdQiTugmmk7v1ebO9Es=,tag:nrio3OXjezRpToALGropMw==,type:str] +SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:SQI=,iv:2Lkoi0oqfIc0zmjN9Vhnx2VzY1wrJRkSqBlvNp+Uo94=,tag:DZBh8W2H7bUiw9DxM+cPDA==,type:str] +SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:NfNjTbF1osVIAEF6Y1TPDpTlPkHBCKInPeZ1Rs3PCim2hXshPsQ5QHcwW8g0pUHo/2CnWja/8TBO24NyPHDjzntRZTQ/tOC6eev3nqJ6Pg==,iv:Ot3Gpm9vIKRTindhjT3wqAUQStwUnKV625Inj6pmrII=,tag:arLmEwlueAif36JhDnBTAQ==,type:str] +SMTP_HOST=ENC[AES256_GCM,data:e3DJ1gpIzxtGVXHf6n2PP8UkX5rZL1uRRcfMlXveDXj+SA==,iv:9MQ41GRAEAAmxWNyWOYSoyVeQmBFBNKoeFkson18YkM=,tag:LaDIH6q7pzp0PShuXMQtpg==,type:str] +SMTP_PASS=ENC[AES256_GCM,data:rG7Xp9JfDixk1GChjZQ1jqHc0q3dHo7E9Qrp/omKqPL4G49enesqxpaQOuk=,iv:by4sItUvFc2joqEFFA+XXviMYrzMBtTtYHE6uQALYJQ=,tag:FTSnskt6fXIT813q8ma7tA==,type:str] +SMTP_USER=ENC[AES256_GCM,data:4rwX5MnYhjkkmZI2S4uP8YGsF88=,iv:kVTS2/QYw9pB3lAdXwe1aamGyIY9uDL1YjG+690f5Vw=,tag:+ndWvP7bbOx0uZ8TSNYX7A==,type:str] +ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:HQ0WvuyNpLPePrhxW+amDBAdhAY=,iv:t4j9BlVkk6ORUKs15+yRq+yG29iOjZ4ALbYxpXfPGPA=,tag:aLjAvQdOQIU6tcNivGb1Jw==,type:str] +ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:yyEB00EblTeQaetIki+HkkJD9Qc=,iv:rB7LgTZ+njQyIgweksvYE4N5wBp3oFdiD7REp8dE34k=,tag:b3O0JZ4is6njdayVSDZXjw==,type:str] +#ENC[AES256_GCM,data:q+qpSfYB6Syd2xwtZ4eiA3T89SI=,iv:UJm2dIhU0FtVLqKLhhT4vdrUBaMg5sKw4px0N+hcebU=,tag:kqaThaRFZwMC3kdi18nrQQ==,type:comment] +OIDC_ISSUER_URL=ENC[AES256_GCM,data:V/vxb+Sfye9R5mhdi5XrGeOZNx+XgUhXekeY3+LRrGIlKb0n4A==,iv:LVGeobkyOMACijrNhyzyDszeGBtY7vSVB7eyJFTLWso=,tag:hlnA7HE6z9j4XfMyg61fMw==,type:str] +OIDC_CLIENT_ID=ENC[AES256_GCM,data:VohyOKTn+u7Z,iv:rWl4sR7LoP41EEKnc9KXaYtoHU+xqZxABSllCnEapjY=,tag:M6/SZ4PzGfB3IVihVtdXSQ==,type:str] +OIDC_CLIENT_SECRET=ENC[AES256_GCM,data:BrW90K5Uql3VB0Ebpl41mEOTAUCvmuJP2KqYu6KfxLmIuziogR0BlzeeWSkFUtAY4LgLBc5F0ln5UCikv9FIKQ==,iv:DYXu2L1t/FISiZ6c5Ys8Ejnxv1w6jIITUeE6KzJOuYk=,tag:4ZavC2+jtmpxYTAUoE/9+g==,type:str] +AUTH_INTERNAL_API_KEY=ENC[AES256_GCM,data:ZrCI90bZIuiqxSa5xowJctgM89ctasZ4ebuoXGAmPQo8EXEn2QSnkcLVUhGzQFU4pp9A9ulqa8IGnNIGuZ0FXw==,iv:GVlcG3D1oiheEfuYBeXj3Sb8K8nEQ8xFiqOqE6deFGs=,tag:I/+ae413+vRpCHXIc+kcaQ==,type:str] +OIDC_ACCOUNT_URL=ENC[AES256_GCM,data:e4loM3VLHL/1JoJKg7sHoO2wm+uNmpdxx/YdIBcUYjFhZMlOusRmnw==,iv:B+K0Q3vgMDJu192TJSV223XUxbbL4+EyWZQUmNBna0E=,tag:MW/LJJ2tApiKjmWCySJy1A==,type:str] +APP_URL=ENC[AES256_GCM,data:IouJCKBAaOvbiVQIZVP5tiPBC90CEg==,iv:RUkURLLViwqSLzDm3ImyZ0BRpXOlpKUVm8eUvkj/NdI=,tag:ohj0zEZGJ0DmVOBMNJfLFA==,type:str] +SESSION_SECRET=ENC[AES256_GCM,data:sqDkEZf705q66q+H0PT3W9baJbBuBmMmwP11IoXiQWR8LNoUqSN68KmwAyeKOp7xcApO+xUoUBGDQGORvrbYV3zflRDpQx/7b1cFw0WScY3npVgkpdttXvOZRvEc/Vdd8OEgNinSsrWNo0qaQGCCeg2HJm2VIpfjMbuuEepLjH8=,iv:FWsQPSXfC7eKDnHIj0QcMxygEal7sJGEh/agUfv1z6o=,tag:udi4h2X2m3995oJYPlYPaA==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuTmNnZ3JFb2RZMDVISFZE\nQ2Q1ZUFrWDZvSUdJSkRKRU9Mb0FST1o3VDJFCklTNW84TzN5TUlWU0FBUVVjVENG\naUQ5SzBLYUFiZEIxWTh1VWloRG9MUkkKLS0tIG9GalM0bkl0NU4wU2R2bE1qTitB\nU0ZYdlF5S3pWVytNSk9TUnY4UFMxWUEKA/bBNRcTmd6mpLrDCz2irehIZZolTXLj\n3y+et9IKE57/xAfNB1n1OHvtQMKEG7VORnccz3zIx7a+y+WH4AixEw==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_0__map_recipient=age1wravpjmed26772xfjhawmnsnc4933htapg6y5xseqml0jdv8z9hqemzhcr -sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnaXZUcHR2eWJFZWpTdGYr\nUVo1RG9tNzlaU0s1RVNwbGhtQnBocWpmQ1dJCms0NWpGa0dBZVN3QTFOSGg2SDVT\nN3VoNmtuMzU2bktBSlg1R3BVMlJTaDQKLS0tIEdDSTFOdzFPaG1HdW54R3hsdTBF\ndzNtd0IwRlF2YlkwdXZlSnQ5ZFQzRFkK7eC7apakezOG8qrZGIy6JgY2onMw2oGO\nB0Q++/YzEfDOt7sipS6/IgWynq2LjmQweJcsRo+P4x8LiKhxmuKkiQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1MzNsdjlwR080VGxyMld2\nRGZQWExFb0hkNk9NRThsUlFWYTNxWGszOEFVCnZYOU9qMHBKM0VCVHEvZXNPVXhy\nbGcrYnBkMmVRTU1iNFV2dEh5eVBzNU0KLS0tIDlEN0hnTHZhWGlWNVV2c1hwVTc1\nTmZsbExVT0F0WUhnMW15OTNVakp5cDgK7aP/iuRWRxG3IGxkLefUuJpiTGhnjWqz\nQ3lj13+JZoRsyhQ5PAamp5Gk9lwz0HKImcVciRak9dtbA93jh1B3Tw==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_1__map_recipient=age1vhftscteyrwphx0jpp0yl60xxrjs77jq05mkzv88js7ckc926vcqepp2cj -sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHbDFXUGRMWFdJVkZpSm1y\nOE00U1FRbEtCVnhWbXN6N3FQVkxvNWF5NWdNCkdaZ2E3d1VkamFMQjRHUzhGTGJB\nTjQva1VpdUdBbi9mRWdHN3pxYyt6bE0KLS0tIEdFVFJodC9tWWNJOW45WGdDeXFv\nS3h5cHlnNVlNU25oSUlOTlBsZFlSUk0KbztjhSLmznefAXgvroXIj9g5SaNXdjnH\nS8wrDSFixtT0o6ZOC+R0qg3Ny9txbztq8cvY3DsqrQjw5xca4AhEXA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYNDBvTjVPaXVnejhkMFV4\nTmxaVTBCSWhoWjZOMjVmYWptU2lrYTNLd0RjCmJMZ09sWVk0QmZ4TjdqQ2t6ZllP\nenIzTE13enNmUG9LSjhmQUk1UEdpZkEKLS0tIHFHVjBYNStQRXlZSXFwMkJpUUhU\ncm9WZ2QzeVdRWlBocXczZW5nazdIQzAK/tPMt5LtxsdWfkeiqyFZRhh1iOmdl40l\nurpDJagyjIxQwIwA5kF5JhyVcND2LdNFyqnfW2BCbMJpRRNleIeW0A==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_2__map_recipient=age1slx6e48k7fre0ddyu7dtm2wwcqaywn5ke2mkngym3rpazxwvvuyq9qjknk -sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2cWlKczAxbXJYQ29FNVlO\ncDd2bEY1Sm1DbnZrOWl2cm82c0FWYitEOEZNCmVlRjFUdGRIV05mVkNIUlo2S0t3\ncFFsRXp1Wk1KaThNSTc5Qmk1akViMTgKLS0tIGxyU0pDd2NrVE1neUlnSE9KcVZT\nWEp1SFNQVjlRR3IxTXJzU2wyZUNaOWsKlBCNRxI/V6f8p6SUkh/FnzvZw0WSeRa0\nuSOH65C34wBw7F/fWqRDSnjrbNp4iGH1GPNUh7ogS4ZkodY2VQqohA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0ME9La0xTTlRuRHVPcE5a\nR1RWYnM1ZmNSNGJ4NGJzd1JVNFpZaWY5MFRRCnIybkl4ZmE2bGdUSmdLYkNhSkhr\nTjJoMmUyZXBkVXZ3VXl4bmRCOExpZU0KLS0tIEh4MlhjTVp5dWNNckdhNGx4S3Zh\nQlp2d3lsbTJHbk9GeS94TFdRSkYrQ1UKLsR70qm9Nca0TrL66vEsowx4K09jaCmf\n1keF5VRVIwNNtTgMsWM2UyjeqjOcXyExcqXhu6Khvrqs5qGVV+TzPQ==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_3__map_recipient=age1vfhyk6wmt993dezz5wjf6n3ynkd6xptv2dr0qdl6kmttev9lh5dsfjfs3h -sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKTWxPaFJkTi9EZkVsdXov\nZC9WSVJPejhaNGg2RU10eHZ2dXBscWxQNXd3CnZxYitoeXhkVXhmOEJDSG90Y2dM\nbFBmNlJJMlJ5dm0ySXpyTjZvMGFqTWMKLS0tIGhWQkY0Q2RwR3lpRFJWYzNid2N0\nbWNYK2Nlc0E4ZklORGI0eHpUU2xSeU0KnbN1ppQhOJPVVjJ3p5Rk0jemcRQq+RgM\nBKJLfupw9yz2fsYIOn2bRU84JMGswDZd9KD/9hOKLQrES7V0UxlDZw==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaZVVSUWNXRGVhSnh6YW1y\nU244MEFCa2lNYTNTcnNPaUd1ZGlvR2txZGc0CmpjblNzalJzYllxRlNPUXEveThB\nSk15SllUanZNL3VVbFViOU1KeitzQ2MKLS0tICtkNEpjVS9VenNKY3NUcDdPSnpr\neEwwNGlGSEdudFZxdjZKTG1BWG5HMFEK0Ai4UkVQK8r7QiEtqRNVwr9T599NuHAA\ney6dypbqPfZx8SfbS+6v4wN/AQpIqyPcRQpWbwaQTdkp8ysKDkEoHg==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_4__map_recipient=age1jwuvzyghfer7rx3qtqa4vs0gxyff0sg6pqgmqvp5zlhnpmvrkdlsdha4kx -sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWNmhYYmVnay9MNHJlOFlR\nQU1KU1UzeGpobCs0RkZEcERJM0R2eHVzVEVjCmhTeDNPUmN0VVhnNWNNN2pLMXpT\neGZFdzFHSmY2c1FRVmdtbXY3Z2FkbWcKLS0tIFRweFVad09KNDd5QjJPbkEvdjBo\nRDAxTWQyWkNVb2hoRGFTRWRaZzF1SkUKYICTvgSDU5Zvh5Xwkj6PYYO4+l4NXd4M\nn3FMQ/HnpwPQB5YTDCNGW64RPgg7DizKQYhwJfvouN8jppNgLS1S3w==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqMzJtVGpaZVFtTkpTZEM3\nWnc5TWM2ZlM2MU9MZllQVVJOM0hBV3pCM2kwCk40K1VNbk1lVXJnQXRDT2Y2OHJM\nTVpENzhQdnAzT0NadkpvMWFXR2RKZkUKLS0tIE5OeitiQytZR1ZIelNBeHJDZzRP\neTZxUzh4RHZubktSMVpUNHo1dGdMaGcKK14ecFe+vus+/2PFBZOt6lYmBkAPV5SN\nbtaiRm1ruoGXdCISidvI2EGy/gJqVl6u/QaHlDqlP6PxG5TVF05x5Q==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_5__map_recipient=age1pgxk292zq30wafwg03gge7hu5dlu3h7yfldp2y8kqekfaljjky7s752uwy -sops_lastmodified=2026-05-20T17:17:38Z -sops_mac=ENC[AES256_GCM,data:E57DxTP+vuC9BlaVev4qkxHeHmcFLjTMjuUzvI1UjVdBSQW8ySig/ys2kRbol9I8yOri9IbHlD+Ii2XUIN7z6KhLVIBHoN6462fJU6uJOs8ic72b1lk2XRBFImhzhuvydx7L/MBfXt6+V/1G/ACq+3g0YuTVkMu2oFiR34rwcK4=,iv:APIaikdSLA5HBJPE5DZDQpbdgD26SX5gdUpIRqM0Tlc=,tag:SQR1QHHm3tU06vi4cBaY4Q==,type:str] +sops_lastmodified=2026-06-08T12:56:27Z +sops_mac=ENC[AES256_GCM,data:NzDoKEj+SWiRJgyseSMHUbs88DXUpOuwJAGjZrN9GU50yp/NuXyIxce9q7bCRluSzsvO77udMcd9+9IFgu2WQvRL6R5Fq6hrtU3JsvzInNmijfBZYYnee/44zaAB/UqvFsDazGHv6GuIDXV1KA0lzmIGpipB4+qL+wSIEKUP56s=,iv:uXwM8uddU2Tg07JS8cDPfmFuALu8TFAMn09wl7y6kxY=,tag:JiRhZhSSgYJ56OSGQLPhGw==,type:str] sops_unencrypted_suffix=_unencrypted -sops_version=3.11.0 +sops_version=3.12.1 diff --git a/infra/.env.enc b/infra/.env.enc index c56371cfde..829be6d137 100644 --- a/infra/.env.enc +++ b/infra/.env.enc @@ -1,61 +1,62 @@ -AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:Rb8p/Q7y8T8bj+QsSUoREgvQQ4juEJkkQJOZ4HCEG5cETtMnX2PeKEmGJnvCLDGQxcmcTNY8FOfpoQNQn+c+BQ==,iv:RYVAAggyGs7E3NCFFeYpCMdvv2iGT7Fk+vFUYxkhwTg=,tag:hvs14F7Y8dnBIWf3+Hp/Rw==,type:str] -ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:HHd9xcbgKNhtIFHRXNakSn6eszeI3hfPLfjdgX8CUbP283Q8g/W8naU3FMG43j6CxuAoZXoimo9ua9l2ClqEaL89oYp8UkPf9ySphTDIrwzWIYelEmFDUxv2kxaTIwnyziBSXBsM9Za93IxdU3WBiIBPU/xl89tBywzPTXVVmqk=,iv:0Iv8rAc4NGxYWgQeeIcvUtaIC/e2EigMLIlIpCHw/wU=,tag:+9Ufxrh7cHIHuBZxY8T/EA==,type:str] -AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:afGBZUwTv7JPJxrU8O6IZ0Ff8MA=,iv:D67ERuD+In+ViOquixuLNomlAzxtvFXD3Kg8z7b0Dfo=,tag:imReGZGqRoJC1+8FwSP87Q==,type:str] -AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:PPIXUkRfD/K5pMg73BH0Lr7v2uA=,iv:IOkV8xlarjgPwZaA7MailwtUeNOqY8L6+Gzzjt4jxHg=,tag:XSiuboy5dImloSvVVU0n3g==,type:str] -AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:R4WFN09++pHl96degrNkldpTdXwkW0CzaHugWlrLg4Tst9jhumc88A==,iv:Hp4lbrJ8qjf66FL255nmoYeKKRnV56Oeuwrs4GUrkqQ=,tag:IIJTWj4v8/w6cWKh9lmjzA==,type:str] -AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:SxZyLHf3uqevdyvYbqwzCv3MR9lQ2E41dkcIFuJ7bQvHvj7BvPu7eA==,iv:Pb52mdAjkXdc3Yv2oAqYHMgAoXJmhZtwb9dsUAtm/xQ=,tag:FNuwxcuGBSOKbyXoc4tJUw==,type:str] -BACKUPS_SECRET=ENC[AES256_GCM,data:BQuPEsZJ4nDaPBx6zI1SyE3zI24NqdUj2vOWJJA/83x1osWZ/uIA/CA0E3Q=,iv:isGQZGhJ3qrZzZ/A/3uxDfu3P6OZspJFuh6wsmzZGGo=,tag:dj1S4E6RpXdvo+iKKmJneg==,type:str] -BLOCKLIST_IP_ADDRESSES=ENC[AES256_GCM,data:vOJNtI4XoIt54mUO2G0Gr7Imlf/F,iv:uGte2NDGJ8FDzQr04HEbyy16eL9N3iQzAuEs083woGk=,tag:8QmjriYUgfVv1ea4NGUk4g==,type:str] -CLOUDFLARE_ANALYTICS_API_TOKEN=ENC[AES256_GCM,data:6XTa179pf+WJuQezPfS18iTZa/0otUnG+fGAuVFUedloyFbT5DmHxYWLPJ1pDa7NUpLni08=,iv:LIpI+a2iEELKIE3jolG22toVBsouivpMT8Flp1gxhc4=,tag:TZ1TnmN3gT/Sp5Fu2y6LQQ==,type:str] -CLOUDFLARE_CUSTOM_HOSTNAME_API_TOKEN=ENC[AES256_GCM,data:BT+IafsvZ3vHtB0678VsR1IBsIuaYPsfBKIPwT3xb4wQ8TiTIEE0KRFYSoDsxu11Wg0q0/A=,iv:p3GAMzADfVd7pAffkrP9sgWcKaMUhTePXSeUmE9TSUw=,tag:dwNJIvRS2oTA1LY4z4+V4w==,type:str] -CLOUDFLARE_ZONE_TAG=ENC[AES256_GCM,data:jq/0WRN6Mk1xGwaDRZe9XWiySh+F+ZyjHfDJvg9sxHQ=,iv:ICJiWpiiXTqGv4VVodwXUvaAsQ4KXVGNXEKSTwAUTRU=,tag:TT2pXOQXZh+YKrzfow/Fpw==,type:str] -CONTENT_SEARCH_TERMS=ENC[AES256_GCM,data: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,iv:wJYo1JlO/T1r0V5xV08PWUW/ABKaGWtwliI9v0y9x/4=,tag:6U1yQelpvoBVwczyFGsnaA==,type:str] -DATABASE_URL=ENC[AES256_GCM,data:kpCVMaY3Ha+ybplD9VPvCeRQEt61yoSu0Dn6JR5Dq8PtU1rdA1Ewk0YiCT4=,iv:K5yVw8w7+UsG09xXZTHC4Q0Z0VylRQBVr0h/QuuS7TA=,tag:UnEm3S6LO4/V1NB6mT6biQ==,type:str] -DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:AWe1swwvbchmZR74yfzheNNAeTx0iZhzUS5OoBM=,iv:vm1oWKva8CoTahrJRLEtQpKlcURrScVhQIHOeVSGt7I=,tag:YCmRyYujj1dwBD9KaS6DnQ==,type:str] -DOI_LOGIN_ID=ENC[AES256_GCM,data:ztqYO35m,iv:oXWNxzAPIqaQ9WYrbbi5ESNhT/9s8jakr75wEfP7Aw4=,tag:m8ufweCmoNhbcb0iS5RTkw==,type:str] -DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:uLERMaUTWMrpkiHmRhLW4RT729Q=,iv:THMJshfMlF232SRnYgdz5IcWC7q6h1vB7RpB8+Cnyxk=,tag:DS3eDHZVORVrKE26L7hq3Q==,type:str] -DOI_SUBMISSION_URL=ENC[AES256_GCM,data:oi98KqaBFe3pSAzSH+Rc0GYJR3SA6nicj3wx04J+vx0D/490jPNRfw==,iv:lNFpyU++R77YzGUM9elVCJ+j51G3J8SgOmEBJVtbKX0=,tag:xWZqnH4/b5wYPwoXsfmlXw==,type:str] -FASTLY_PURGE_TOKEN=ENC[AES256_GCM,data:1j93DIsNHb9HJ1DTHMCy+JX95cUIj6rJnAcWXsIEiXw=,iv:PfTYmWxl7lSY6JLhHbnFeJKKVMgFuMVzjum8NbWOiw0=,tag:uN4MGUe+KehHFsSVfwsJ0g==,type:str] -FASTLY_SERVICE_ID=ENC[AES256_GCM,data:cnhHu1xfiGQAZpTbdlmo5F3w0bsiAQ==,iv:8FFbwbJnkgR9vh8NU7sKMTaTKMgCpfjlQqgN4enSu7U=,tag:R+I+XANrlDx8bRo0rJU3jA==,type:str] -FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data: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,iv:wDDidSsOKgcynBnC7bxgADxJT4C61/OmGb2XtLFbIOo=,tag:Pizy5E49y96EYTI1VQp1zQ==,type:str] -JWT_SIGNING_SECRET=ENC[AES256_GCM,data:BGlvfkuWh0iHW/Hj96cZSY66xiK+oChbHzBTpXPLbhcwUYkDOjIF/bjwJZeiVfGwSmfen7ERi6ZjasI6vChiJMCVqdmjShInlaunOEUB0f759kdtqtN6jOKp9ZnMcQ5MlAE3N3XVPhNS0VuBY6F4zwcMeGLDXbZXc7HViUjKtJd+8OttLGgmE7MMjJ5+/ajn42JaGYD9Q6Bb7x4ibb4J2BFRO16m4iH0KQXEoWb20ikkh4H4EyC0h6BgQ49G5hnJIukkziASwDt1dN6NNuRU7RQSkPYi20x35tyDx2u/GxHAEZxdL9S5BHQV7PW4OyP7Kw9pOmVSFmrIiHIO3V1Hf2O2+Tm2b1qtxkZagMmXjMOyurtAoKlfXLIpEdXumSWZivFdnkfyXrGp8cvlajY1fTG87Q8n/C78AJ/Z8oiwN05IursUlHbSE2xWmoY8IEoLvphfZSZ2aZoeBUbe0+sjnK8Utkd2vInwhZUaPo+78jmAfHtcscIMzzAdZV5u7qkelkhDWOuo9ORKSbZ+MqcuSSNekUqIiA9UE3dnkYLgVtM/6B08nU9i4HkzXFyHh0AqmOMqdSBjXXSdAMPV+AjadNUGdyE33lTzPQun6VfiUNuOTt1NCD4IjS/fklvdzKuw+xkIZ/VhGEIr+FNxJJUnT6gDHKkAXLVotXYXwBJfiWU=,iv:10/6CnMbjNucMtV686xPWHAkFVzzl/SutwG5qafOtO0=,tag:UHFHQ7swB7kLS9XkknSKKA==,type:str] -MAILCHIMP_API_KEY=ENC[AES256_GCM,data:DsCvDCEZ3fHGc6W4XMFdN1OHLi1zC9+fwAToBOOs7PFO2z2V,iv:8XOGBn/W0OyhbLO2dYre0ukgk9xX40u3M/vLttz3BFY=,tag:7YNavzArdtVh8LoTKKf2ew==,type:str] -NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES=ENC[AES256_GCM,data:V4k=,iv:aqYkd18RYpa7kuuzbpAmSk9Vcr47BW8kIZm9gKEwEXU=,tag:RIsIsobpnql49/0WX7ymVQ==,type:str] -NODE_ENV=ENC[AES256_GCM,data:KwOcuP7/y4p1EA==,iv:T989Sim7c2uyqTH8uL6yeAPajoYJahzFemZcSyI/Sss=,tag:mkChCafe8w2VZy5a52tRhQ==,type:str] -PUBPUB_PRODUCTION=ENC[AES256_GCM,data:XjBuCw==,iv:nSFjSKPbf4Uu6hME/jDQxce3cYH1pJO8DJQMF1NyWKU=,tag:NmH5qyOtM96tX5EDIR1cTg==,type:str] -S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:/QG2ZvWm5+yRLQ9jk2WoiAjJMI4=,iv:8zSs4ZHAVpf/ZHkkugQqrpCQeF8aKUCOwEeE/Xoknlk=,tag:JIMyV0NLIZy26dtgrTK66w==,type:str] -S3_BACKUP_BUCKET=ENC[AES256_GCM,data:ahjpBwf2y41SpCM=,iv:fUODBbghyloP8U8PbKACtr55E7cm1UmgC7CbpTHs8l4=,tag:LfgUFA5rGG4zqw9JMb/UTQ==,type:str] -S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:ovFYPVj43nPuTmg/UtA1JDtyUxToGLuGFMZEVc/lbEmfeqI=,iv:rQ+oqx7YraJkJMBB39GNaHAQtI9jUAeehv0BdmWBUts=,tag:oyW7YFacdo9br6m27u5Awg==,type:str] -S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:3Bj6Gffv8F9xrpfh6WkEXmDIsCMSASObbHR20oP2tUZfw15q4ev1fw==,iv:kDmAFX4YXr9pqtRJoqtPlucXZGl5mWso4FpzuGo+ZhQ=,tag:Jdw9gj6IXNAdolEBSvhT3g==,type:str] -SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:PUaTTaw3pyiUbuCm0WDBoNKwt8rUv2gKKzX0sROPDCLfXxgwaCWTV6nZwjxyaryIpsfpL2x0zfvKH/AjnvLc0AFbBO9sU+cCrq3yuQFCuK2T4olrOitaZGbigHpiEtCPM/laCRS5vxGhbENynWM33mz+jHUEsKNFcQOyKzb5U6SibDS5Cs1WeFoPGObslsfR9FinmMpehf0bvHgneEur0kPw7iHdtpDIJf1/1+o9YcRqJwvaaUx+ZVXYVA==,iv:gd5qwJM6wMUOxwXcDZMPUPXbfSRRr29ZMEZX+SxStFo=,tag:/v6LTnbX71Rf6inniPCCbA==,type:str] -SENTRY_ORG=ENC[AES256_GCM,data:5mlX,iv:HYvoEOkVMOTw5I4/5n25G/4VJGp3cgU7TKYFpvbTsG8=,tag:6a9akdj+cQUhusG2gxi5bA==,type:str] -SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:qSw=,iv:i+u6W2yUFvEZhgJwWoMj6sQTE3InQrm781t7b3f10gI=,tag:hEwRJ6hP+66kskzxsf/sgQ==,type:str] -SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:wTLkeHcl5sRBZwS0cN76m7wzK08jMgaGbENvxqLOLDajwV6QcI1s86CGey3HHpef4iUX22ZKuFZ9Q8FyS4x/XwQi1cckvzjznqF45N6BXQ==,iv:yr8bcynfv7ASsta0iyB0I3ex2Yej+lcUE1XdmGkrD18=,tag:h5NFEQ0tWsfCra7v+wQXcQ==,type:str] -SMTP_HOST=ENC[AES256_GCM,data:BUyE1bVMOJEJOtgHqkHU9hxxMcM4BN6se/ErfQvZjvTYkw==,iv:JaISCEPObi0iArR0dr9dqSg6AxIFJbFGGYRewntPFxo=,tag:Lr2xuIvVz9MIwVXvb01wNw==,type:str] -SMTP_PASS=ENC[AES256_GCM,data:jDTmSuleP6u35yLS+u6R7Pm3jgOM1sKTBajDZ9QWZ5pBUN5LdI/X8Kly3vA=,iv:q7OLmKSfYT1ggmF5vL3QijvwoWBzLbsZ9AsZBXxDWhs=,tag:CtAOweypxrewqTLbxEIowg==,type:str] -SMTP_USER=ENC[AES256_GCM,data:pr660T3ADIaK06QaP3WHaD19nj0=,iv:fNEeFbvdPa+QYyXpGGJNkUCZmBvtuU/j2c0w1HLlTqQ=,tag:u83hapQheqPzh06iELenQg==,type:str] -ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:TnNAGrCWHBPFJn/bdvXBG+dcTkI=,iv:xvQtGH/6zaRL4LgtAnO4zloLBh8SxnHByasRo6PTuec=,tag:8Bg3x/oVwLEroJCY2aA+ww==,type:str] -ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:ujfa/HTCpDoosNoa6TxDF6UQM3E=,iv:EdC4fX9W8XdObL35eNRzcT2UgUNmRfH3NAeLgqytAUI=,tag:GErhJOFLqVhia2G3rdJ0PA==,type:str] -#ENC[AES256_GCM,data:tUzJpG36v1MCZVwtDivOa2dPI9E=,iv:XAaV6kSZUxcAj8W3R8tjiAu+ZIKyFaGiOReyBg1x4A8=,tag:TZQErGhvNehnHw8G76Y0VA==,type:comment] -OIDC_ISSUER_URL=ENC[AES256_GCM,data:7FcCegV2iNhxPWuZcXLt33MpOjxKoGZQTzT3lQhjpEsn,iv:/OQgpmtPttmd3Zm9TFUi0U1xaQOp2Jh0hrjp1g8cHsA=,tag:S2aWuK0BSN4f5wupxd9Mig==,type:str] -OIDC_CLIENT_ID=ENC[AES256_GCM,data:rRPEdmmq8tyb,iv:K32MKM7A8mj7zJ1rnKzAYTVaAjl5gEB0gtrdMtCSYYU=,tag:pH7S/4tulQjantSnBr4SfQ==,type:str] -OIDC_CLIENT_SECRET=ENC[AES256_GCM,data:QaSFOmYu68bG0zAjSstcaZmh8jgH36eRKiu450gCFsJomt5+Z7egA8UNqRTvLf6i7FQ+gJvBDUvqSzEpZNuuXQ==,iv:JsTveBXK/CH/gD6YaL4IQ3vyJGujIXmRH4ydmrvj87Q=,tag:qJVn8dPnmgIEQTPpCMPchw==,type:str] -AUTH_INTERNAL_API_KEY=ENC[AES256_GCM,data:S3S2Gq8xnsvlfKnoaOEaZ7Akpn9cZQtazJGTay0k9Baq7uqZRSy+IWjoB2CiYLr/CAtESwcHweY2FcslltJrmg==,iv:6PGhhLcsORNTJH/xFzbZrAh5mx2UNR7bB85vhOYPEp0=,tag:sc0VggJh77D4GtMyKfmIIw==,type:str] -OIDC_ACCOUNT_URL=ENC[AES256_GCM,data:tmhgeJpCj3kX52riHjncNk7nVNBUw1ic9EzSOlyW9HEOr83t,iv:k5+OtNyPHhgBF0XXpaCVS8q5HoJhYw5QeV4q/Fgu0ss=,tag:kyUUke7FJ13UQsJSxG4zrA==,type:str] -APP_URL=ENC[AES256_GCM,data:qNnlTBK+bpluTRPCL3gHGgekA5FtUw==,iv:FMAbRxulpga3W+A/bmSZbrmtaY8Cgmqu4gJMEqSFlps=,tag:DnFx1Y9Rhyho80fTQof3qw==,type:str] -sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyOW8xclhZZldKbnN6VGtR\nQjIvUFNrdXBRTTQ5RUtiNklsaUFOWkZwd0ZRCjNnbjFIZnZPeG1oT3c0Tm5CaG1O\nRXJPY1pSS1JET3BqaGprME4zTVhPVFUKLS0tIHcwemZWbFpTdlFuSHBBZFgvSHdV\nMkFFNkI0ZGFKVEZET3h1bW51OXJwRHMK0LpTnZaAak+N3h58yiSJMzY/Xw44iC6t\n5okiCdXSTB/fl8VJAtaNwqRS93dLwdzRAPO94KitKtYdeQlE2s4tHA==\n-----END AGE ENCRYPTED FILE-----\n +AES_ENCRYPTION_KEY=ENC[AES256_GCM,data:cOPQNsv+RcNZTFMNlfWJVTxtxn+gvH6Zl+8mnhrT3ozqq3Hdsof1RdcX//89a9Iv8eZydYL4lr69xX+1EF++kA==,iv:XROpTjhUe5xKKvea2wF29CrKX1tyb74ryYGtmTZW7M0=,tag:u504jpFVEv9qhWKKzGeDEg==,type:str] +ALTCHA_HMAC_KEY=ENC[AES256_GCM,data:CgI0iDGU92PNsv0+bCz5DQ9IuijEO81o9R2eUw5obrI+T574A54Rk/1AC6W20a3LMzNbr1PL/bzus5kRDQHkF4FrnhgqVAJkwKt1Y3WuSaxg+OjfJOUqQ1X4eatOdAYGE5WTA1J43iH72GncnXKhjCRLnNm9poYUJjQ40Q8W71w=,iv:mv3bbcduBHNY+R07jQRJ9eE/Kf+zXHU9VC9VRbAeM5E=,tag:Y+Can7QvinaJjiq574iltg==,type:str] +AWS_ACCESS_KEY_ID=ENC[AES256_GCM,data:aX+2Ka6L/MNvDhXgulu4L4C+ghY=,iv:7quN1JRNHa/hDIoVOLrhGLUyoWJdhIZLVWlT26TZPWY=,tag:PgyV3ksl45SqY7ICaPng7g==,type:str] +AWS_BACKUP_ACCESS_KEY_ID=ENC[AES256_GCM,data:IYqt1d59GbFH3lsEpZbg2AQ38TA=,iv:0xWSArQOyLCbAG3X3gXudbcxZo6lN4M4HVHOi0WI/+0=,tag:H0fMJzwW4XzOVYXMh+dGWA==,type:str] +AWS_BACKUP_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:IYPtX85aqoH2dyURPih/FFbmtQRtXeuw0/oGAcAAEr6PcldL86Haog==,iv:gY0wmXGxCwW1LlOmI6+SJ0yTquYv7lpUYIAkeRQheRQ=,tag:Uzf4k8gx8EtAebyxfYycxQ==,type:str] +AWS_SECRET_ACCESS_KEY=ENC[AES256_GCM,data:cXZ6ZsJpljEywGQw2JW9QxDVXCbbmIvIEJpxYz858RCk813cHK0mRg==,iv:OE2D/07/hHEipLAOPc5yJIO+Ajhe8eYYjosyX13xO3I=,tag:YRsDWikln4e7n55B98eEcA==,type:str] +BACKUPS_SECRET=ENC[AES256_GCM,data:jLXRFwG8z2zLUHn6oAvwYvYD5x//B+8L/yPgkYqZdQXygHekzhDY9PxBBTc=,iv:qIb+e8dLHvV+pD1zbIzhz44LLJABmFRGBjVm9TVOkv4=,tag:NoDbZmBgKh5psEFE9X3NYw==,type:str] +BLOCKLIST_IP_ADDRESSES=ENC[AES256_GCM,data:wZ6YiKvHmkY9MwhMhd1YGOI/VRva,iv:KyQmQES2gbWS/3+q0fkasULnRO/eFevZ+qZDnNclQik=,tag:7HiTTrxRM+or7DyhbeTrfA==,type:str] +CLOUDFLARE_ANALYTICS_API_TOKEN=ENC[AES256_GCM,data:n9DSo77rUErM95XtJHgi+O8CzUUWbRVuVLL7/Sp9x2xrxG3LjaHZmvqK1AUEbAYYMg5WdSE=,iv:heH6hMW+P84ki0TrbWqasdNPEXs4WO3BPHaa9aG6QAQ=,tag:8anGNcbulSXNm2k1P4Am5A==,type:str] +CLOUDFLARE_CUSTOM_HOSTNAME_API_TOKEN=ENC[AES256_GCM,data:+mvm1v5cXj9cpAv/ZxEFfim7wO75EmTkiC7FJG2WlOMqe2MhWAcXMGrBxwADiNT7ilLPpEw=,iv:7BwPmUHr/ofEhiIKZWeIvwTN8uyyrXIdb2WduBuOKq0=,tag:2WnhKxkycWDyhVLp6z3hKQ==,type:str] +CLOUDFLARE_ZONE_TAG=ENC[AES256_GCM,data:1tVB8TRGUeYoHijJ8Kyy5zNkeAdmstTnLX6GBg0CMwg=,iv:9boEV85hBUaul/n5CxzoVQ9YFs86byKfqOIZeUj9TKk=,tag:NQhEm4yF8MuG+n2TK4UPCg==,type:str] +CONTENT_SEARCH_TERMS=ENC[AES256_GCM,data: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,iv:mx6LMrYyo+q07DsrustxTpDDTFjNJ5iD9kQ6BnWG2CU=,tag:wVlrmz39K32fKc9dXA3ZhA==,type:str] +DATABASE_URL=ENC[AES256_GCM,data:F224sfnbPS5/QXPy0IxXsI0zSnEfgTiw1ZjzmmxS128eSzIUqbG8FWT97uY=,iv:2XYO5vdYeY9o00Y+JEgoig7ntXuH6LiRPp/yPT4e6YI=,tag:V8T7I4nBlGlOMXA+7p5ETw==,type:str] +DATACITE_DEPOSIT_URL=ENC[AES256_GCM,data:Pj2SwZDs5WyggQwlY159kATmMtBHpsdvQnfn+6A=,iv:pev02Jl0a8M6NE1CSH6Z5cvbEf4VqysNZk7CuHS7GwM=,tag:4XsRvzIgsGEp47Kd3hrncQ==,type:str] +DOI_LOGIN_ID=ENC[AES256_GCM,data:VorprjAy,iv:G0Fu5Y2xw8+y+/kEoZmxybX11RuMVdya7/MU4MDpJLA=,tag:0MP06dbqBrpJIvuBUvr2KQ==,type:str] +DOI_LOGIN_PASSWORD=ENC[AES256_GCM,data:QG+H3ggMKBDBlitMoqsycZo+14U=,iv:hol0//NNUVkcpokLIJKq0mj+F+qa/vbPwmbO3dVIUVc=,tag:jz7glytv9To1r6rMtmjLoA==,type:str] +DOI_SUBMISSION_URL=ENC[AES256_GCM,data:OSJ5BwyF01ac2UMJC8kXLNxblkPFL3AP+Xe41546iuaZMoE1gwMlnw==,iv:WSjEfc6rc8WK9AmE7ZOdQ8WNwSg1x/LjjJQgjr5EwA4=,tag:XyAijTIwvZrmmA2edM3AvA==,type:str] +FASTLY_PURGE_TOKEN=ENC[AES256_GCM,data:1ux9Y4fMRjG8zb8M/HIamjfu5kuGOAtYQUZCwQGFFeM=,iv:eVXgazKAjZmgeWKkZXW+aO63VwM6VVXDmmjZd+sZBNo=,tag:zJdJybZzuCB8XrAPsgLDPg==,type:str] +FASTLY_SERVICE_ID=ENC[AES256_GCM,data:X4XNvStBxhaSzZ4weW2W9NFuHbha3g==,iv:MpzTpTtp/GUhA0iE5TjIwtf5uNjb5LJqyuv66ChOmf0=,tag:UfiELOz/IXSue7K2TINvpA==,type:str] +FIREBASE_SERVICE_ACCOUNT_BASE64=ENC[AES256_GCM,data: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,iv:BY4LcN0RygyXL0zquJO8HGDzoGLHmfmZF78JbbK4aHs=,tag:RvcdWaeNRmRNrsItA0qaqQ==,type:str] +JWT_SIGNING_SECRET=ENC[AES256_GCM,data:X4uE1LIUeeG8aVidioIyWd7AvW4GgyCthn6RFZpVC9MYTuRTDTdo8MvFw10r9uXs+jJn5uA9aDTOnAl1AW6qn8qxg9cqayQ5GBqNIXlZz2iv4QfuGiBDmYiktIqcDZnQyoZXk9I8kGfOIyB2jGeqWmDwE4cQmcjk8YBepSJ/16spp/fAF8ysFLlx7COb6ZiyPnykEtweKDsD4rlSwoNIAaJi9RWQLahk55d9peV846W890Yf4t0wEop4gXJd+KjASNMT7Q+sKa9VKbRNjBdG5Q+yo8eJB8V0MUoJEpWBtwBhlYA+7BCt+V76EEMs95LqZEn4JvzyLyPeBOim0xu8Cq1mLZ5dxJQ3OY7ZUurzBy6gFlMe7+b0ny+vQrx5qbDQO2N66+9vUFwHg57xfztlf4xIyEfF1MNzkZTrRgeJ4VWyN9/CdWRo7z/p5XMJ8KKONeHXD2UbQ4SzcICS/Kmf3Qc82bmuyh5LcWBsyGhMrJYe0xE8YfaVGbjX0AvStAAK0AoTvbqRU69ixwwRr11H6NDUiSMxDvnNaIVw0DWRrpb0751h0TMH/bd9+kVYKojENohZySURdKGqfl1/+szqS90rDPMT77a57/BSasKUaUXFdzZwX3BcYE3lbi9vUxgubxuHwowoNQBgM1P10F7RQfu3CH6Zz39ZG8rwh3Zr9m0=,iv:o3jtNg6GtCrd6BO03AbdZpxyxI8Rot0Kllld4JZ1hi4=,tag:eTADm9K8oV4eTMvvnIrmkw==,type:str] +MAILCHIMP_API_KEY=ENC[AES256_GCM,data:kUMsTJPEW8bVg+T1TAwrUVgqNPlE+f0jjxhRsOGM2PA63ZOO,iv:wyw3amP8woxmCyQzaky2qtr+cNV0w7UXDA2zmEdGlhs=,tag:O/mYdk2Qcp0e/dpOclOO0w==,type:str] +NEW_ACCOUNT_LINK_COMMENT_WINDOW_MINUTES=ENC[AES256_GCM,data:9TY=,iv:qfyP7iUNYhKJ8JvvLSAN2dtjNv1yh8YtD/V5Qlq+lMo=,tag:FM+oyJBwCjQyH9x4g/xTYg==,type:str] +NODE_ENV=ENC[AES256_GCM,data:9UkWrXt7EEHYmw==,iv:w77pQ68jjL5MgZaMEa+FeIsIH5bk33awNRCiYAsicro=,tag:On32RZ0nHlDdT0q59PF3yw==,type:str] +PUBPUB_PRODUCTION=ENC[AES256_GCM,data:a73OjQ==,iv:LtxENFujQBhRKUduDC4IpapHFfN69D9aVGB4n2GsAP4=,tag:BJVJu6ZOAi7/JFKrM18VUw==,type:str] +S3_BACKUP_ACCESS_KEY=ENC[AES256_GCM,data:MySMbh81XGLI5tFuh8tsCLyD7A4=,iv:fw1QRxfZ4Gp9t0UZTzu2yWqELAtOeHe7fSTPM52Maeg=,tag:+jzVhEWajZoqAyLSMgLLUw==,type:str] +S3_BACKUP_BUCKET=ENC[AES256_GCM,data:a/up4sDPefeo30E=,iv:94TW24zXROaDVWlN2ZvBTOvshZHDLt48Bm6ShrJJclM=,tag:2k3kGN5W1pRwxZb+lMpveQ==,type:str] +S3_BACKUP_ENDPOINT=ENC[AES256_GCM,data:QDt4Rt67UPtxD5WmeQkzLIi9Cn5+g3g6FlCSQ4toKNH5mXk=,iv:naZ9+ld5glWT6/vC3+bBFSy8lkb1cziI4xw/WPq11ZE=,tag:YoPbjn7nuDo/xikS4CIfOQ==,type:str] +S3_BACKUP_SECRET_KEY=ENC[AES256_GCM,data:0f37EfI8ar2r3QcoEgRPqC7CFf2rcrt97ndKIYc437EbI8Pdlk9jdQ==,iv:lxLupG+FS4XRePa5ajIAEt3EFlGuyd9rsFR+dP9TRMY=,tag:57CFfF7BxvHvh1EHGcGpyA==,type:str] +SENTRY_AUTH_TOKEN=ENC[AES256_GCM,data:42YV4KkGJ5NgJNl1piN/67qnZFxh40yjFU8j/TaA/11Y8B8Z3qir4vw4yBf7HTELl+4buB00fePvle2vNZpOg0zjxAkgrrCM36rsA//0cBjtQw6fSjE9BPlLGNOHXAKjv/DB81SsUiPAi35zFdiX/h5qUgym07AA1tUFJvmwDwfUTlKZE8DlaJ5fStxpByJJSgP1PD22/Iha29YUTqSYGcoaRNw6ZyNADBNnoBSiQzOdUrXJ62jOV2eGyw==,iv:VaH/CiMCoIGJvXNOvTgv2N32zDeDf7Ze7d4M82r29sU=,tag:zGvCgeY8f1qjWI0KhPLjIA==,type:str] +SENTRY_ORG=ENC[AES256_GCM,data:yjaV,iv:tL4SSm0NzWIQtaYTnFi4qtQRj3jN5s1d/Uv+W8h2Y88=,tag:pVLj3gc+4b4Mh8tjfzSP/w==,type:str] +SEQUELIZE_MAX_CONNECTIONS=ENC[AES256_GCM,data:83o=,iv:uGUPifRTnZNtmy2k1i+cbN9n4yTUL100tpC08ZvP6/Q=,tag:5VRaNf/kuxcQ/pH/gwM5ig==,type:str] +SLACK_WEBHOOK_URL=ENC[AES256_GCM,data:lYIQmaDhO7Zp969itMAskL7Cn5w6588AR3Dw0eB5GCotjsfgzeMIL27J2uB3eMr11nR9CL2yH/KnD6kMPfgU2LDuwnurXSQ86CzDTohZOQ==,iv:fou0nzLU4709vo0RFUYQpAeQ7bEk1d7nghXti5Uk9WY=,tag:MRVym71KxiWpYCSgT3XhgA==,type:str] +SMTP_HOST=ENC[AES256_GCM,data:dnGA3t3YXVR9hrKimISU0RaMPksB3jWQ+U3JmDoVmY8flA==,iv:Lp7pp+sT3KmiF/gYOmBlmTr3LIrf+3nlyNP8Hv5ggAQ=,tag:f//9MfsryaSsj7mhhdKFZQ==,type:str] +SMTP_PASS=ENC[AES256_GCM,data:XWk3kR+hmL4IYzptnDsckP0WyIuxCuhZQtd3tyquwJoI4L9sEk2QEAbG2lk=,iv:JplsZ1L9FFHjjD8Sl9MzOkXLJoVle6MwVXMzFNN/cxQ=,tag:Y1R6JVKMGXvzEh9UCzPtuQ==,type:str] +SMTP_USER=ENC[AES256_GCM,data:QGmg9fyTLSONjYpD99CVcAcyj0Q=,iv:WdOs4I/xpLgDxpF/CnFc2phodloUrhPMIpWtule60V0=,tag:qBVV6G+Qt9tfAzuqyfWuTA==,type:str] +ZOTERO_CLIENT_KEY=ENC[AES256_GCM,data:zlGoscYHyaixR99G8qBNA1Am/Ck=,iv:7JjsPQJY8N+wj3dBIxmFqeqV43OY7gof5NaTqRjB6PU=,tag:nduNYfItfL/Fd8jwn+fKFw==,type:str] +ZOTERO_CLIENT_SECRET=ENC[AES256_GCM,data:Xwy3/Vz09Liqaemjq0QKZtCygfA=,iv:g369aMdX4NXeezLewz/iYemkGD5Kmxr5Kc+bcKA/L00=,tag:HUalG+yDNDZRp4piNDJcQQ==,type:str] +#ENC[AES256_GCM,data:dAa2qTb6v6vSW0M+kURGfdZytIc=,iv:9nCOq16BDlKafPloj5XCMbJS8KFGeC3ujik/G9f4Z1w=,tag:KLw0D/4/Y4V/EdheTR8H/A==,type:comment] +OIDC_ISSUER_URL=ENC[AES256_GCM,data:AwLBf7ga60P004EJ4lttj+bWn5dowmHyqlhITAaNwlDF,iv:1HTt6buEuNe/5DIWovFBiq7X/7kM38rWwy25PjI7/eU=,tag:ryqx2cAV9TVMbfoNpsz5lQ==,type:str] +OIDC_CLIENT_ID=ENC[AES256_GCM,data:3nz4Ht1O/20Y,iv:ZNZGpWTxAvaI96jgGaTjwhhNCpMAmmMUXy+zH2xSVVI=,tag:gfUQdlXE3inaaMaB3xqG9A==,type:str] +OIDC_CLIENT_SECRET=ENC[AES256_GCM,data:0/em3c5Qw83VsKeX0qg6SsEow1F8y6Dy06XXcEjizCP/U8XUscav1N/50K8cC/3txy3qeLuqjgb/JBA6Dq5ApA==,iv:DxsPhhtD4WYZvwikbEKP6hpDz2vPqYH/PtWmMFMUiUM=,tag:0ngiKyuQnkj9cY3MxqKErg==,type:str] +AUTH_INTERNAL_API_KEY=ENC[AES256_GCM,data:DCLGhZ23XlhgA3+7B2ylH4BknMU7kmYTpdAVmQeBOtojDfAEo0ZNuX9BQJ3C0LotL66nx3Epw4J8mlAyzOaKVA==,iv:nPzmiM5H/AB+1mkZlqMdZzmEX4eNH7teuHwsSlAMb6c=,tag:zq1BEAZ3jMIOdhocpbxUzQ==,type:str] +OIDC_ACCOUNT_URL=ENC[AES256_GCM,data:mUkv1Wp/0AkONfbbFA9GjEeQzLSKrWWsCv/92nRrlxdNVVJd,iv:l+O3TvVFk6nhtkFx9EWobNoQZLIZHh7+jfHEQGj2Yc4=,tag:n5FC/OPp7Vs/wS/xqqhvdw==,type:str] +APP_URL=ENC[AES256_GCM,data:1zzq+e+m5NCyE0fErenR/LLUYwxKTQ==,iv:0wMkUNyct5ndzl0KrToVRR0jBnSTnNOD/N2IX1p+nlY=,tag:WWAols+LyHJ0tjskaIfHEA==,type:str] +SESSION_SECRET=ENC[AES256_GCM,data:UHKZN55SGAteEePQDmC+hnp7GagVmMyDnAuszAhpA0LlcXo+G3GLu0M0vMIaVP3HZT2yYn1PquQMp7/ED7RQVobIxgg8bYOoOA8+hTknH/SPOzDNw4BBh0TZKKwNYxp6//sPGc7bYgzx7giqx0JYGQ6Wm2km8yycg3WmHTviNJw=,iv:QPWwyrraZx+/jGcSEB0kACBRWqyCdhGhmbA3KxuuVdI=,tag:sNkR5aN5m1eqFDXE5NPhVw==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0UWdpUjdPb3V6eEx4RjYz\nOWJnb1hkZVNaYml4dHNXWGttWDJUQnZrMmlnCkZFTnpkejdJN0llSFVIQVlQK0pJ\ncC9JMG1VY1VqMlNnTXNtV2Jxb3JxSmsKLS0tIFg4ZmJ3bzJDbjVGUUJ5TjgveERM\nakZ6SHJzVVArTnFVQ2dtMmZuQ0RQVEEKDBR8kuBfkiIs9A1ZcgG5uINJN2kZw9K7\n5o5gRZZWK0NvL5+176J1Okj3On4Qp/8Ma393eUEIKjppcpixashuUA==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_0__map_recipient=age1wravpjmed26772xfjhawmnsnc4933htapg6y5xseqml0jdv8z9hqemzhcr -sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpWFZKYWg0bDJ6QmJMaXp0\nZ2tnbDA1aFFycmh5TDJMV0pzam5HTlR1LzNRCnZ0cEQ4ZGRNMm5NRFVJRWV1NGNo\nc3dOLzBVK1RRbWY5dS8wL240RFphRFUKLS0tIGIxMTV4VGdaOVRhWlBNOUlmbGln\nbFIzdUc0NEF0Ymc3N1RzakZBSDN2ckUKkAdNqWbWaIS5SK1Wd4nMq2eGTttfGd0i\nlgGytU6HINzF9yU7OAeK73Q6WWunHHy9DUYoD3dl8tedbxN7FlDxsA==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2NVVuTnRFUXgwemd6c1pa\nM3JlWU12QVFkdTdadkxyVU1Ba29pNjVNdngwCjBtYmpPZmxOSWEwUCt2akluVE1V\nZTlzZGdLY29JeHNJSFFzVUIvaFhVYWsKLS0tIENDMHYzTDdTRk1mZlRod21HSWdR\nQUUrdThna2dqM3RGWm5kYlN2MTRhVm8KnB6sn6KnuUyScuicyenPCW7U0H+QoX1K\nN2zXSeIrCHld/qSo/VnL7G4lCj/FtblutvIpkQrJuKtRs86SUHo0ZQ==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_1__map_recipient=age1vhftscteyrwphx0jpp0yl60xxrjs77jq05mkzv88js7ckc926vcqepp2cj -sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2SXJDTUJoS0NqWVZ6cnRB\nYk9YejhWclVwTkxSSGJSelJJeDNrYnB3eUhnCmprYnRlTElpajA3TEFCTlk5YTdQ\nZWdTTkpyUVUyVVZuNnQycmtGZmhaVGMKLS0tIElCeGcxb2NqdEhwSytsWGtPSVU2\nTFJxS0VsWFFBbm5reFBQRkZaOTVneUEKuMJjoNAQtQipFP9Kod0ejlO1SX9PpWB2\ncR7Q3VcIUf7t5u+pnpJ7e56lHHcaAfiOUQFsShvjjXBLwXTeFu3IJg==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_2__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2aWw0RWh1TmVld1NkQzFa\nSlc4eFBFZXBHSmJtOGVmeTVVdnBOZWtvNHdVCkxJemFXdXhobnFzaG1Ccjh3akQz\nZE8yTDdTTHZ3dDIvOXZKVCtqbHB4YjQKLS0tIDdpVUQxU0U1dXV3ZUtMZW5RZ0E5\nKzBDVjJVdGMwb2VNNGJaYWNoTHZ3dk0K35AwRO8duSEXY71X6PztTo9dO7nHzNpr\nVgGrqsC+SuJQaArW6gTJEddV9Jd3igrFtxnrqACcqnxqvOboniiiNA==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_2__map_recipient=age1slx6e48k7fre0ddyu7dtm2wwcqaywn5ke2mkngym3rpazxwvvuyq9qjknk -sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJUzVqRGJUUllLbFJGSlRC\najM4L2lqclcyVWpYcElVbGlsTm9yaXE0a1hBCmFRcDRXV3Y5RHNvL1VtV1Y4UG5P\nUDdYV08zV1gwS3I3QU9aUlhyV3hITzQKLS0tIEpLZzBPV0V1VVJtRkVjd2lmdjFB\nSjdKWHJQakF1K3ZRZzFNanBkSFNhNkUKTq/DTismWQDjyf+L8fxq2VOiNUCLXAse\nfujiuMVcrYIKXP8yR2tAyylsdDzto/g4e5RzX93/GsMnlvWrPfPZJQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_3__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsUGljMzBPOCtxdlNkTmZC\nV0dWdm1KT3NaNDUvdHFEUXJQSnk5bUlFWEFRCncxUmpNcFdPQjIydytKWG5ZL01x\nK0pVWjBQSWlnd2RDK1VpZFI0L1hEYXcKLS0tIGZEdnlnVGhFdHkzL0N6eFhHa0JG\nOVcrRS82UzA3eWY0V2trRS8wUHl4RGcK2SGPRYR4S5timTppkKbTU4wAMvyY7Rb0\nrRhw+0rIRmkqw7BgkkaVCKTj/L7MDT2Am7wYp0Lat/yhKgNTbiTs3A==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_3__map_recipient=age1vfhyk6wmt993dezz5wjf6n3ynkd6xptv2dr0qdl6kmttev9lh5dsfjfs3h -sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpRXdaTFRLa2F3Wkg2T25o\na3V2aU4zZ0RRYVFoYjI2OCtTWURNcWtYTEhNCkNIcW9Zcm9GR2JOUTZ4UlBUSXV2\nenJNVExldnFBeEZZbzMrRVZuaWRFQ1UKLS0tIEJUMS9QbkRMazJpRE40bjBJbDlP\nZjk3SkhTQ1J5RFk0WDJKMS9tUENrRVkK1d9PJZF74p9GdFrmSLazCXBjgXRwNZ9G\n0QDbPasLQze8o9s55irb8vTAI+yQsdJnupHR8qDxj0AAsSRyl6Nt9w==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_4__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4dEVPRFMvaXdpODdRZVI5\nSFhZNEFxRVY0eElRRW9wK1lPTHVubkpWaTNvCmFrWmc1NHQwRjVBdk91WWR3aVNZ\nNFhEbDJGTVlrN0w2dmNSbmNGWkNBdHcKLS0tIDY2cUQ5Y2NEMHE1LzhYVjJJT29F\nNW5xN2NQTWg3UzV1NTRTMjZlMnpYdUEKFBnojIyphHykPB2qsksx2YK2ouuHWaDg\nV4I5aRq9pkaCScWBqDm754MwMGN64+5uwbFD1cAFReBw1Ui4UJm0ZQ==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_4__map_recipient=age1jwuvzyghfer7rx3qtqa4vs0gxyff0sg6pqgmqvp5zlhnpmvrkdlsdha4kx -sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjK0o4TEtERVNlNCsrTG91\nSkg4WktLa0xMc1hUbVBtTS84ZGhZQ3NRWFdFCnlQRmVjdklya3lEamdESjQ4VWpM\neG9kaGpyVVJadjY5cUwwc1NpUi9lSU0KLS0tIFRERTlEM3FQYlM0WjhsZ2dNekhm\nRlBPb2p6MWV0b2dudmNxUVgvcldQNFEKvogefgMFzKyL6VjrbNUWxTMDKl0+CeAR\nbf+3TNzTxurazzgqNRgUheXZ9mv4YKo5Yu1MNgI6Rm0JJwfZryogsQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_5__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsNHVZSXgwa20veTZpYkIv\nTm1hWHhVSXJnYkQ5QjZHK0xETzdCM2s5SHlrCkZMYllNaU5WNmpKN2Z0MVJyWGJI\nUVVDOE4ydkhzenpxL1E5dm4zTEp1aTQKLS0tIFAzblhpQ0grUWVBMUxHaUVmc0NO\nNDRJT05TajBuUEJYVGFJbDhXS01ZbTQK/XYWizwEUT6xgSwn4HXXkBDDxvFNHk/R\nE3DVZwvrrSI4pXuLqZmFzjvWWjpE4TUTqOO44t/eQpaLw85dfE2RHw==\n-----END AGE ENCRYPTED FILE-----\n sops_age__list_5__map_recipient=age1pgxk292zq30wafwg03gge7hu5dlu3h7yfldp2y8kqekfaljjky7s752uwy -sops_lastmodified=2026-05-20T17:17:46Z -sops_mac=ENC[AES256_GCM,data:aysQdMNX85UzCFkaOdAJWm6mV8XSpCA2f86VMGLcuMa0AoCsAf9DClVQh78OI/Ut9mDOPqKr7/UBSUJSVveP5x08vCvXaRTyX+BbSobD1Qfbbx7d2Z66XC7FyEv7dVz+P5LBCSQWBpTGASP9DqWlmen6uTpYJB8oqQc6Bw+84tM=,iv:+RR0Kk8gVnwvtqKh9y/6O92Ymmc2ksvJZnzyFaXaFvQ=,tag:6B2VEwUw/c5cMEaF0TQ4ag==,type:str] +sops_lastmodified=2026-06-08T12:56:23Z +sops_mac=ENC[AES256_GCM,data:/br5w2fm20q6SMjAhcaGpSYHBsuv52+j6JnwRk5uI/iF/lwSeQU5P7hfSiNXzg0xfp4dmYi4gzNaRw8AtWsrqSiOv3n82xXkgLnVShyHujnJ/lw9EpZf0rw0URnQn13ynAH1QcnVZAN5b+TukyDdYlUIJQwNf0KmotyegAQZaBo=,iv:s19uoR/7AxcN9BQ7LXe4lVJaucbyMAlMlnbcid6XtV4=,tag:m6LxZ2wMSBZPWyBakyOacw==,type:str] sops_unencrypted_suffix=_unencrypted -sops_version=3.11.0 +sops_version=3.12.1 diff --git a/infra/.env.test b/infra/.env.test index 6b446b9f35..03b5a99c13 100644 --- a/infra/.env.test +++ b/infra/.env.test @@ -35,6 +35,7 @@ DATACITE_DEPOSIT_URL=https://deposit.com SLACK_WEBHOOK_URL=https://slack.com SENTRY_AUTH_TOKEN=xxx SENTRY_ORG=xxx +SESSION_SECRET=shhhhhh # AWS_ACCESS_KEY_ID: Required # AWS_SECRET_ACCESS_KEY: Required # AWS_BACKUP_ACCESS_KEY_ID: Required diff --git a/server/envSchema.ts b/server/envSchema.ts index 453dbffc65..b65adcd987 100644 --- a/server/envSchema.ts +++ b/server/envSchema.ts @@ -205,6 +205,9 @@ export const envSchema = z.object({ 'JSON array of search terms for the "By Content" tab. Each element is a string or [name, ...aliases]', ), + // ── Session ───────────────────────────────────────────────────────── + SESSION_SECRET: z.string().min(1).describe('Secret for signing session cookies'), + // ── Testing ────────────────────────────────────────────────────────── INTEGRATION_TESTING: booleanish.describe('Signals that integration tests are running'), TEST_FASTLY_PURGE: booleanish.describe('Enable Fastly purge calls during tests'), diff --git a/server/kf/api.ts b/server/kf/api.ts index cfd0a05d0b..0428807a4e 100644 --- a/server/kf/api.ts +++ b/server/kf/api.ts @@ -8,7 +8,7 @@ docker service logs auth_auth --tail 50 2>&1 | grep -i "error\|invalid\|authoriz * POST /auth/logout — clear session + redirect to KF Auth logout * * Internal service-to-service endpoints (AUTH_INTERNAL_API_KEY): - * POST /api/kf/profile-sync — receive profile updates from KF Auth + * POST /api/kf/webhooks — receive webhook events from KF Auth (profile, bans, sessions) * GET /api/kf/branding — return community branding for login page * GET /api/kf/summary — return community list for a KF org * GET /api/kf/billing/usage — return usage stats for billing (placeholder) @@ -30,6 +30,7 @@ import { isDevelopment, isDuqDuq, isProd } from 'utils/environment'; import { buildAuthorizeUrl, + decodeIdTokenClaims, decryptPayload, encryptPayload, exchangeCode, @@ -37,8 +38,15 @@ import { fetchUserOrgs, generateCodeVerifier, OIDC_ISSUER_URL, -} from './auth'; +} from './oidc.server'; import { provisionLocalUser } from './provisionLocalUser'; +import { + handleSessionRevoked, + handleUserBanned, + handleUserSessionsRevoked, + handleUserUnbanned, + handleUserUpdated, +} from './webhookHandlers'; // ── Helpers ────────────────────────────────────────────────────────── @@ -85,6 +93,60 @@ function isPlatformSubdomain(host: string): boolean { return host.endsWith('.pubpub.org') || host.endsWith('.duqduq.org'); } +/** + * Set the silent-reauth circuit breaker. It MUST be visible on the community + * origin where silentReauthMiddleware checks it. On platform subdomains we + * scope it to the parent domain (like pp-lic) so a breaker set on www.* is + * also sent to the community subdomain; on custom domains it's host-only + * (and must be set on that origin — see failRenew / /auth/renew-failed). + */ +function setRenewFailedCookie(req: any, res: any): void { + const onPlatformSubdomain = (isProd() || isDuqDuq()) && isPlatformSubdomain(req.hostname); + res.cookie('pp-renew-failed', '1', { + maxAge: 60 * 60 * 1000, + httpOnly: true, + ...(onPlatformSubdomain && { domain: isDuqDuq() ? '.duqduq.org' : '.pubpub.org' }), + }); +} + +/** Clear the breaker — matching whatever domain scope setRenewFailedCookie used. */ +function clearRenewFailedCookie(req: any, res: any): void { + res.clearCookie('pp-renew-failed'); + if ((isProd() || isDuqDuq()) && isPlatformSubdomain(req.hostname)) { + res.clearCookie('pp-renew-failed', { domain: isDuqDuq() ? '.duqduq.org' : '.pubpub.org' }); + } +} + +/** + * Bail out of a silent renewal without a session: trip the circuit breaker so + * silentReauthMiddleware stops redirecting, then send the user back to where + * they came from (anonymous). Used on every renewal failure path so a single + * failure degrades to "anonymous page for 1h" instead of an infinite loop. + * Crucially never returns a 500 — Fastly restarts 500s on GET, which would + * re-redeem the one-time OIDC code (→ invalid_grant). + */ +function failRenew(req: any, res: any, host: string | undefined, returnTo: string): void { + const protocol = isDevelopment() ? 'http' : 'https'; + // Custom domains: this callback runs on the platform domain (www.*), which + // can't set a cookie for the custom origin. Bounce through /auth/renew-failed + // on that origin so the breaker lands where silentReauthMiddleware checks it. + if (host && !isPlatformSubdomain(host) && host !== req.hostname) { + res.redirect( + `${protocol}://${host}/auth/renew-failed?return_to=${encodeURIComponent(returnTo)}`, + ); + return; + } + // Platform subdomains (and same-origin): a parent-domain-scoped breaker set + // here is visible across *.duqduq.org / *.pubpub.org, including the community + // subdomain the user is actually on. + setRenewFailedCookie(req, res); + if (host && host !== req.hostname) { + res.redirect(`${protocol}://${host}${returnTo}`); + return; + } + res.redirect(returnTo); +} + // ── Router ─────────────────────────────────────────────────────────── export const router = Router(); @@ -94,21 +156,37 @@ export const router = Router(); router.get('/auth/login', async (req: any, res: any) => { const communityHost = getCommunityHost(req); const rawReturn = req.query.return_to || '/'; - // Validate return_to is a safe relative path (prevent open redirect) const returnTo = typeof rawReturn === 'string' && rawReturn.startsWith('/') && !rawReturn.startsWith('//') ? rawReturn : '/'; - // Generate verifier first, then encrypt it with routing info into state. - // This avoids cookies/session for OIDC state, so it works across - // domains (custom domains → callback on www.duqduq.org). + const isRenew = req.query.renew === 'true'; + + // Pin silent renewals to the account the expired session belonged to. + // The pp-lic cookie carries the hashed user id of the last login on + // this domain; the callback compares it against the renewed identity. + const currentLic = req.cookies?.['pp-lic']; + const expectedLic = + isRenew && typeof currentLic === 'string' && currentLic.startsWith('pp-li-') + ? currentLic + : undefined; + const codeVerifier = generateCodeVerifier(); - const stateToken = encryptPayload({ v: codeVerifier, h: communityHost, r: returnTo }); + const stateToken = encryptPayload({ + v: codeVerifier, + h: communityHost, + r: returnTo, + ...(isRenew && { renew: true }), + ...(expectedLic && { e: expectedLic }), + }); - // Pass the community hostname as context for per-community branding. - // The branding endpoint resolves hostnames → slugs. - const { url } = await buildAuthorizeUrl(stateToken, codeVerifier, communityHost); + const { url } = await buildAuthorizeUrl( + stateToken, + codeVerifier, + communityHost, + isRenew ? 'none' : undefined, + ); return res.redirect(url); }); @@ -120,6 +198,27 @@ router.get('/auth/callback', async (req: any, res: any) => { const { code, state, error } = req.query; if (error) { + // All prompt=none error types mean "silent re-auth can't complete" + const isPromptNoneError = + error === 'login_required' || + error === 'interaction_required' || + error === 'account_selection_required' || + error === 'consent_required'; + if (isPromptNoneError && state) { + const renewState = decryptPayload<{ + v: string; + h: string; + r: string; + renew?: boolean; + }>(state); + if (renewState?.renew) { + // Mirror the success path: in dev the hostname middleware + // rewrites localhost → demo.pubpub.org, so an absolute + // redirect would send the user to production. Relative + // redirects keep the browser on its current origin. + return failRenew(req, res, renewState.h || req.hostname, renewState.r || '/'); + } + } console.error('KF Auth error:', error, req.query.error_description); return res.status(400).send('Authentication failed. Please try again.'); } @@ -128,8 +227,13 @@ router.get('/auth/callback', async (req: any, res: any) => { return res.status(400).send('Missing authentication parameters.'); } - // Decrypt state → {v: codeVerifier, h: host, r: returnTo} - const stateData = decryptPayload<{ v: string; h: string; r: string }>(state); + const stateData = decryptPayload<{ + v: string; + h: string; + r: string; + renew?: boolean; + e?: string; + }>(state); if (!stateData || !stateData.v) { return res.status(400).send('Invalid or expired authentication state.'); } @@ -151,14 +255,34 @@ router.get('/auth/callback', async (req: any, res: any) => { const user = await provisionLocalUser(kfUserId, userInfo); + // kf-auth session id from the ID token's sid claim — stored on the + // local session so the session.revoked webhook can target it. + const kfSessionId = tokens.id_token + ? (decodeIdTokenClaims(tokens.id_token).sid ?? null) + : null; + const protocol = isDevelopment() ? 'http' : 'https'; + // Silent renewals must come back as the SAME account the expired + // session belonged to. With kf-auth multi-session, the active account + // there may have changed since — switching identities must be a + // deliberate user choice (via interactive login + account picker), + // never a side effect of background renewal. On mismatch, bail out + // and leave the user logged out. + if (stateData.renew && stateData.e) { + const renewedLic = `pp-li-${getHashedUserId(user)}`; + if (renewedLic !== stateData.e) { + return failRenew(req, res, host, returnTo); + } + } + // For custom domains, we can't set a session here (different domain). // Create a one-time encrypted token and redirect to session-set on the origin. if (host && !isPlatformSubdomain(host)) { const sessionToken = encryptPayload({ u: user.id, r: returnTo, + s: kfSessionId, exp: Date.now() + 60_000, // 60 seconds }); const sessionSetUrl = `${protocol}://${host}/auth/session-set?token=${encodeURIComponent(sessionToken)}`; @@ -169,6 +293,13 @@ router.get('/auth/callback', async (req: any, res: any) => { const logIn = promisify(req.logIn.bind(req)); await logIn(user); + if (kfSessionId) { + req.session.kfSessionId = kfSessionId; + } + + // Clear silent re-auth circuit breaker on successful login + clearRenewFailedCookie(req, res); + const hashedUserId = getHashedUserId(user); res.cookie('pp-lic', `pp-li-${hashedUserId}`, { ...(isProd() && { domain: '.pubpub.org' }), @@ -182,6 +313,16 @@ router.get('/auth/callback', async (req: any, res: any) => { return res.redirect(returnTo); } catch (err: any) { console.error('OIDC callback error:', err); + // If this was a silent renewal, never surface a 500: Fastly restarts + // 500s on GET (vcl_fetch), which re-redeems the one-time code and + // produces a confusing `invalid_grant`. Trip the breaker and bounce + // the user back anonymously instead — they retry in an hour. + const renewState = decryptPayload<{ h: string; r: string; renew?: boolean }>( + req.query.state, + ); + if (renewState?.renew) { + return failRenew(req, res, renewState.h || req.hostname, renewState.r || '/'); + } const detail = isDuqDuq() ? ` (${err?.message || err})` : ''; return res.status(500).send(`Login failed. Please try again.${detail}`); } @@ -196,7 +337,9 @@ router.get('/auth/session-set', async (req: any, res: any) => { return res.status(400).send('Missing session token.'); } - const data = decryptPayload<{ u: string; r: string; exp: number }>(token); + const data = decryptPayload<{ u: string; r: string; s?: string | null; exp: number }>( + token, + ); if (!data || !data.u) { return res.status(400).send('Invalid session token.'); } @@ -214,6 +357,12 @@ router.get('/auth/session-set', async (req: any, res: any) => { const logIn = promisify(req.logIn.bind(req)); await logIn(user); + if (data.s) { + req.session.kfSessionId = data.s; + } + + clearRenewFailedCookie(req, res); + // Set the CDN cache cookie on this domain const hashedUserId = getHashedUserId(user); res.cookie('pp-lic', `pp-li-${hashedUserId}`, { @@ -224,70 +373,81 @@ router.get('/auth/session-set', async (req: any, res: any) => { return res.redirect(returnTo); } catch (err) { console.error('Session-set error:', err); + // Trip the breaker so a failed transfer falls back to the anonymous + // page instead of looping (and avoid a 500, which Fastly would retry). + setRenewFailedCookie(req, res); return res.status(500).send('Failed to establish session. Please try again.'); } }); +// ─── Silent re-auth circuit breaker for cross-origin communities ───── +// When a renewal fails, the breaker must be set on the community origin (where +// silentReauthMiddleware checks it). For custom domains the OIDC callback runs +// on a different origin and can't set that cookie, so it bounces the browser +// here on the community origin to set it, then returns the user to their page. +router.get('/auth/renew-failed', (req: any, res: any) => { + const rawReturn = req.query.return_to; + const returnTo = + typeof rawReturn === 'string' && rawReturn.startsWith('/') && !rawReturn.startsWith('//') + ? rawReturn + : '/'; + setRenewFailedCookie(req, res); + return res.redirect(returnTo); +}); + // ─── Logout ────────────────────────────────────────────────────────── router.post('/auth/logout', (req: any, res: any) => { // Clear local session req.logout(() => { - // Set pp-lic to logged-out state + // Set pp-lic to logged-out state. Must use the SAME domain scope the + // login marker was set with (callback/session-set), otherwise on the + // duqduq deploy (where isProd() is false) this 'pp-lo' is host-only and + // fails to overwrite the .duqduq.org-scoped 'pp-li-…' — leaving the user + // looking logged-in to silentReauthMiddleware, which then loops. res.cookie('pp-lic', 'pp-lo', { - ...(isProd() && - req.hostname.indexOf('pubpub.org') > -1 && { - domain: '.pubpub.org', - }), + ...(isProd() && { domain: '.pubpub.org' }), + ...(isDuqDuq() && { domain: '.duqduq.org' }), maxAge: 30 * 24 * 60 * 60 * 1000, }); - // Redirect to KF Auth's logout endpoint so the SSO session is also cleared + // Redirect to KF Auth's signout relay so the SSO session is also + // cleared. (The relay POSTs to better-auth's sign-out — a plain GET + // redirect to /api/auth/sign-out would be rejected as POST-only.) const returnUrl = `${process.env.APP_URL || 'http://localhost:9876'}/`; return res.redirect( - `${OIDC_ISSUER_URL}/api/auth/sign-out?callbackURL=${encodeURIComponent(returnUrl)}`, + `${OIDC_ISSUER_URL}/auth/signout?redirect_uri=${encodeURIComponent(returnUrl)}`, ); }); }); -// ─── Profile sync (webhook from KF Auth) ───────────────────────────── +// ─── Webhooks from KF Auth ────────────────────────────────────────── -router.post('/api/kf/profile-sync', requireInternalKey, async (req: any, res: any) => { - try { - const { userId, givenName, familyName, displayName, email, image } = req.body; +router.post('/api/kf/webhooks', requireInternalKey, async (req: any, res: any) => { + const event = req.headers['x-kf-webhook-event']; + const { data } = req.body; - if (!userId) { - return res.status(400).json({ error: 'userId is required' }); - } - - const user = await User.findOne({ where: { id: userId } }); - if (!user) { - return res.status(404).json({ error: 'User not found' }); - } - - const updates: Record = {}; - if (displayName !== undefined) updates.fullName = displayName; - if (givenName !== undefined) updates.firstName = givenName; - if (familyName !== undefined) updates.lastName = familyName; - if (email !== undefined) updates.email = email.toLowerCase(); - if (image !== undefined) updates.avatar = image; - - // Recalculate initials when name changes - if (givenName !== undefined || familyName !== undefined || displayName !== undefined) { - const first = givenName ?? user.firstName ?? ''; - const last = familyName ?? user.lastName ?? ''; - if (first || last) { - updates.initials = `${first.charAt(0)}${last.charAt(0)}`.toUpperCase(); - } - } + if (!event || !data) { + return res.status(400).json({ error: 'Missing event header or data' }); + } - if (Object.keys(updates).length > 0) { - await user.update(updates); + try { + switch (event) { + case 'user.updated': + return await handleUserUpdated(data, res); + case 'user.banned': + return await handleUserBanned(data, res); + case 'user.unbanned': + return await handleUserUnbanned(data, res); + case 'user.sessions-revoked': + return await handleUserSessionsRevoked(data, res); + case 'session.revoked': + return await handleSessionRevoked(data, res); + default: + return res.status(200).json({ ok: true, ignored: true }); } - - return res.status(200).json({ ok: true }); } catch (err) { - console.error('Profile sync error:', err); + console.error(`Webhook handler error [${event}]:`, err); return res.status(500).json({ error: 'Internal error' }); } }); diff --git a/server/kf/oidc.server.ts b/server/kf/oidc.server.ts index 0544a1e423..c1b49f4c5c 100644 --- a/server/kf/oidc.server.ts +++ b/server/kf/oidc.server.ts @@ -145,6 +145,7 @@ export async function buildAuthorizeUrl( state: string, existingVerifier?: string, context?: string, + prompt?: string, ): Promise<{ url: string; codeVerifier: string }> { const config = await discover(); const codeVerifier = existingVerifier ?? generateCodeVerifier(); @@ -165,6 +166,7 @@ export async function buildAuthorizeUrl( code_challenge: codeChallenge, code_challenge_method: 'S256', ...(context && { context }), + ...(prompt && { prompt }), }); return { url: `${authorizeUrl.toString()}?${params}`, codeVerifier }; @@ -178,6 +180,28 @@ export interface TokenResponse { refresh_token?: string; } +/** + * Extract claims from the ID token without signature verification — + * the token came straight from the token endpoint over a trusted + * server-to-server channel, so its contents are already authentic. + * `sid` is the kf-auth session id (requires enableEndSession on the + * OAuth client); it lets us correlate local sessions with kf-auth + * sessions for the session.revoked webhook. + */ +export function decodeIdTokenClaims(idToken: string): { sub?: string; sid?: string } { + try { + const payloadPart = idToken.split('.')[1]; + if (!payloadPart) return {}; + const payload = JSON.parse(Buffer.from(payloadPart, 'base64url').toString('utf8')); + return { + sub: typeof payload.sub === 'string' ? payload.sub : undefined, + sid: typeof payload.sid === 'string' ? payload.sid : undefined, + }; + } catch { + return {}; + } +} + /** * Exchange an authorization code for tokens (server-to-server). */ @@ -271,6 +295,50 @@ export async function fetchUserOrgs(userId: string): Promise { return data.orgs ?? []; } +// --- Outbound ban sync --- + +export async function syncBanToKfAuth(userId: string, reason?: string): Promise { + if (!AUTH_INTERNAL_API_KEY) return; + + try { + const res = await fetch(`${AUTH_INTERNAL_API_URL}/api/internal/users/${userId}/ban`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${AUTH_INTERNAL_API_KEY}`, + }, + body: JSON.stringify({ reason: reason ?? 'banned via PubPub spam system' }), + }); + if (!res.ok) { + const text = await res.text(); + console.error(`syncBanToKfAuth failed for ${userId}: HTTP ${res.status} ${text}`); + } + } catch (err) { + console.error(`syncBanToKfAuth failed for ${userId}:`, err); + } +} + +export async function syncUnbanToKfAuth(userId: string): Promise { + if (!AUTH_INTERNAL_API_KEY) return; + + try { + const res = await fetch(`${AUTH_INTERNAL_API_URL}/api/internal/users/${userId}/unban`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${AUTH_INTERNAL_API_KEY}`, + }, + body: JSON.stringify({}), + }); + if (!res.ok) { + const text = await res.text(); + console.error(`syncUnbanToKfAuth failed for ${userId}: HTTP ${res.status} ${text}`); + } + } catch (err) { + console.error(`syncUnbanToKfAuth failed for ${userId}:`, err); + } +} + // --- Exports --- export { diff --git a/server/kf/webhookHandlers.ts b/server/kf/webhookHandlers.ts new file mode 100644 index 0000000000..beeced67c9 --- /dev/null +++ b/server/kf/webhookHandlers.ts @@ -0,0 +1,125 @@ +import { User } from 'server/models'; +import { upsertSpamTag } from 'server/spamTag/userQueries'; +import { deleteSessionsByKfSessionId, deleteSessionsForUser } from 'server/utils/session'; + +export async function handleUserUpdated(data: any, res: any) { + const { userId, givenName, familyName, displayName, email, image } = data; + + if (!userId) { + return res.status(400).json({ error: 'userId is required' }); + } + + const user = await User.findOne({ where: { id: userId } }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + + const updates: Record = {}; + if (displayName !== undefined) updates.fullName = displayName; + if (givenName !== undefined) updates.firstName = givenName; + if (familyName !== undefined) updates.lastName = familyName; + if (email !== undefined) updates.email = email.toLowerCase(); + if (image !== undefined) updates.avatar = image; + + if (givenName !== undefined || familyName !== undefined || displayName !== undefined) { + const first = givenName ?? user.firstName ?? ''; + const last = familyName ?? user.lastName ?? ''; + if (first || last) { + updates.initials = `${first.charAt(0)}${last.charAt(0)}`.toUpperCase(); + } + } + + if (Object.keys(updates).length > 0) { + await user.update(updates); + } + + return res.status(200).json({ ok: true }); +} + +export async function handleUserBanned(data: any, res: any) { + const { userId, banReason } = data; + + if (!userId) { + return res.status(400).json({ error: 'userId is required' }); + } + + const user = await User.findOne({ where: { id: userId } }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + + await upsertSpamTag({ + userId, + status: 'confirmed-spam', + fields: { + manuallyMarkedBy: [ + { + userId: 'kf-auth', + userName: banReason ? `KF Auth: ${banReason}` : 'KF Auth (external ban)', + at: new Date().toISOString(), + }, + ], + }, + skipKfAuthSync: true, + }); + + return res.status(200).json({ ok: true }); +} + +export async function handleUserUnbanned(data: any, res: any) { + const { userId } = data; + + if (!userId) { + return res.status(400).json({ error: 'userId is required' }); + } + + const user = await User.findOne({ where: { id: userId } }); + if (!user) { + return res.status(404).json({ error: 'User not found' }); + } + + await upsertSpamTag({ + userId, + status: 'confirmed-not-spam', + skipKfAuthSync: true, + }); + + return res.status(200).json({ ok: true }); +} + +export async function handleUserSessionsRevoked(data: any, res: any) { + const { userId } = data; + + if (!userId) { + return res.status(400).json({ error: 'userId is required' }); + } + + const user = await User.findOne({ where: { id: userId } }); + if (!user) { + return res.status(200).json({ ok: true, skipped: 'user not found' }); + } + + if (user.email) { + await deleteSessionsForUser(user.email); + } + + return res.status(200).json({ ok: true }); +} + +/** + * A single kf-auth session was revoked (user revoked a device from the + * Security page, signed out, etc.). Delete exactly the local sessions + * that were minted from it — they're stamped with the kf-auth session + * id (the ID token's `sid` claim) at login. + */ +export async function handleSessionRevoked(data: any, res: any) { + const { sessionId } = data; + + if (!sessionId) { + return res.status(400).json({ error: 'sessionId is required' }); + } + + const deleted = await deleteSessionsByKfSessionId(sessionId); + + return res.status(200).json({ ok: true, deleted }); +} diff --git a/server/middleware/silentReauth.ts b/server/middleware/silentReauth.ts new file mode 100644 index 0000000000..0767980e77 --- /dev/null +++ b/server/middleware/silentReauth.ts @@ -0,0 +1,43 @@ +import type { NextFunction, Request, Response } from 'express'; + +const SKIP_PREFIXES = ['/api', '/auth', '/dist', '/static', '/service-worker', '/favicon']; + +/** + * Detects "was logged in, session expired" and triggers silent re-auth + * via OIDC prompt=none. Only fires for browser page loads (GET requests + * to non-API, non-asset paths). + * + * Uses the `pp-lic` CDN cookie (set at login, 30-day maxAge) to detect + * that the user was previously authenticated. A `pp-renew-failed` cookie + * acts as a circuit breaker to prevent redirect loops when kf-auth's + * session is also expired. + */ +export const silentReauthMiddleware = () => { + return (req: Request, res: Response, next: NextFunction) => { + if (req.method !== 'GET') return next(); + if (SKIP_PREFIXES.some((p) => req.path.startsWith(p))) { + return next(); + } + + if (req.user) return next(); + + // After logout it's set to 'pp-lo' - renewing would resurrect the session the user just deliberately ended. + const lic = req.cookies?.['pp-lic']; + if (typeof lic !== 'string' || !lic.startsWith('pp-li-')) return next(); + + // Circuit breaker: recently tried and failed - skip + if (req.cookies?.['pp-renew-failed']) return next(); + + // This 302 carries no Set-Cookie, so Fastly would otherwise cache it + // under the per-`pp-lic` cache key (vcl_hash only mixes connect.sid in + // for /api routes). A cached "go reauth" redirect would then be served + // even after the user has a valid session again — an infinite loop the + // session cookie can't bust. Mark it private/no-store so the edge + // passes it through (Fastly return(pass)es on `Cache-Control ~ private`). + res.set('Cache-Control', 'private, no-store'); + res.set('Surrogate-Control', 'no-store'); + + const returnTo = req.originalUrl; + return res.redirect(`/auth/login?renew=true&return_to=${encodeURIComponent(returnTo)}`); + }; +}; diff --git a/server/server.ts b/server/server.ts index a201775a9e..abbdb30eac 100755 --- a/server/server.ts +++ b/server/server.ts @@ -15,7 +15,7 @@ const app = express(); const appRouter = Router(); -import { getAppCommit, isProd, setAppCommit, setEnvironment } from 'utils/environment'; +import { getAppCommit, isDuqDuq, isProd, setAppCommit, setEnvironment } from 'utils/environment'; // ACHTUNG: These calls must appear before we import any more of our own code to ensure that // the environment, and in particular the choice of dev vs. prod, is configured correctly! @@ -35,6 +35,7 @@ if (env.NODE_ENV !== 'test') { import { communityBanGuard } from './middleware/communityBanGuard'; import { deduplicateSlash } from './middleware/deduplicateSlash'; +import { silentReauthMiddleware } from './middleware/silentReauth'; import { blocklistMiddleware } from './utils/blocklist'; import './hooks'; @@ -70,6 +71,23 @@ import { server } from 'utils/api/server'; // set BLOCKLIST_IP_ADDRESSES to comma separated list of ips (or partial ips) to block appRouter.use(blocklistMiddleware); +// Fastly terminates TLS at the edge and forwards plain HTTP to the origin, +// marking TLS requests with the `Fastly-SSL` header (see vcl_recv). Both +// express-session (`proxy: true`) and express-sslify (`trustProtoHeader`) +// decide "is this secure?" from `X-Forwarded-Proto` only — if that header +// never reaches us the `Secure` session cookie is silently dropped and the +// user is trapped in a silent re-auth loop. Normalize the proto signal here, +// before any of those run. This only touches the header used for the secure +// decision; req.hostname/req.protocol (and community routing) are untouched. +if (isProd() || isDuqDuq()) { + appRouter.use((req, _res, next) => { + if (req.headers['fastly-ssl'] && !req.headers['x-forwarded-proto']) { + req.headers['x-forwarded-proto'] = 'https'; + } + next(); + }); +} + if (env.NODE_ENV === 'production') { Sentry.init({ dsn: 'https://abe1c84bbb3045bd982f9fea7407efaa@sentry.io/1505439', @@ -117,33 +135,47 @@ appRouter.use('/api/health', (req, res) => { appRouter.use( session({ - secret: 'sessionsecret', + secret: env.SESSION_SECRET ?? 'sessionsecret', resave: false, saveUninitialized: false, + // TLS is terminated at the edge (Fastly) and forwarded as plain HTTP, + // so without trusting the proxy express-session sees an insecure + // connection and silently drops the `secure` cookie. This honors + // X-Forwarded-Proto for the secure-cookie decision ONLY — unlike a + // global `app.set('trust proxy')`, it leaves req.hostname untouched + // so community routing keeps working. + proxy: true, store: env.NODE_ENV !== 'test' ? new SequelizeStore({ db: sequelize }) : undefined, cookie: { path: '/', - /* These are necessary for */ - /* the api cookie to set */ - /* ------- */ - httpOnly: false, - secure: false, - /* ------- */ - maxAge: 30 * 24 * 60 * 60 * 1000, // = 30 days. + httpOnly: true, + secure: env.NODE_ENV === 'production', + maxAge: + env.NODE_ENV === 'production' + ? isDuqDuq() + ? 1 * 60 * 1000 + : 15 * 60 * 1000 + : 10_000, // 1min duqduq, 15m prod, 10s dev for testing }, }), ); appRouter.use((req, res, next) => { - /* If on *.pubpub.org domain, set cookie to be accessible across */ - /* all subdomains to maintain login. Especially important when */ + /* If on a platform domain, set the session cookie to be accessible */ + /* across all subdomains to maintain login. Especially important when */ /* creating communities. */ const hostname = req.headers.communityhostname || req.hostname; - if (hostname.indexOf('.pubpub.org') > -1) { - req.session.cookie.domain = '.pubpub.org'; - } - if (hostname.indexOf('.duqduq.org') > -1) { - req.session.cookie.domain = '.duqduq.org'; + const onPlatformDomain = + hostname.indexOf('.pubpub.org') > -1 || hostname.indexOf('.duqduq.org') > -1; + if (onPlatformDomain) { + /* Fastly maps *.duqduq.org → *.pubpub.org at the edge, so the */ + /* hostname seen here can read ".pubpub.org" even on the duqduq */ + /* deployment. Pick the parent domain from the deployment env (the */ + /* same way the pp-lic cookie does) rather than the rewritten */ + /* hostname — otherwise the session cookie gets pinned to */ + /* .pubpub.org and is never sent back to *.duqduq.org, which traps */ + /* the user in an infinite silent re-auth loop. */ + req.session.cookie.domain = isDuqDuq() ? '.duqduq.org' : '.pubpub.org'; } next(); }); @@ -254,6 +286,7 @@ appRouter.use(authTokenMiddleware); appRouter.use(purgeMiddleware(schedulePurge)); appRouter.use(readOnlyMiddleware()); +appRouter.use(silentReauthMiddleware()); appRouter.use(communityBanGuard()); const { customScript: _, ...contractWithoutCustomScript } = contract; diff --git a/server/spamTag/userQueries.ts b/server/spamTag/userQueries.ts index 338d32e109..f83cd0933b 100644 --- a/server/spamTag/userQueries.ts +++ b/server/spamTag/userQueries.ts @@ -4,6 +4,7 @@ import type { UserSpamTagFields } from 'types'; import mergeWith from 'lodash.mergewith'; import { Op } from 'sequelize'; +import { syncBanToKfAuth, syncUnbanToKfAuth } from 'server/kf/oidc.server'; import { Collection, CollectionAttribution, @@ -14,6 +15,7 @@ import { SpamTag, User, } from 'server/models'; +import { defer } from 'server/utils/deferred'; import { deleteSessionsForUser } from 'server/utils/session'; import { expect } from 'utils/assert'; import { schedulePurge } from 'utils/caching/schedulePurgeWithSentry'; @@ -40,6 +42,7 @@ type UpsertSpamTagOptions = { userId: string; fields?: UserSpamTagFields; status?: types.SpamStatus; + skipKfAuthSync?: boolean; }; type UpsertResult = { spamTag: SpamTag; user: User }; @@ -82,12 +85,13 @@ const schedulePurgesForUser = async (userId: string) => { }; export const upsertSpamTag = async (options: UpsertSpamTagOptions): Promise => { - const { userId, fields, status } = options; + const { userId, fields, status, skipKfAuthSync } = options; const user = await fetchUserWithSpamTag(userId); const verdict = getSuspectedUserSpamVerdict(user); const existingTag = user.spamTag; if (existingTag) { + const previousStatus = existingTag.status; const data = buildSpamTagData( verdict, existingTag.fields as UserSpamTagFields, @@ -95,8 +99,14 @@ export const upsertSpamTag = async (options: UpsertSpamTagOptions): Promise); - if (status === 'confirmed-spam' && existingTag.status !== status) { + if (status === 'confirmed-spam' && previousStatus !== status) { await Promise.all([invalidateUserSessions(user), schedulePurgesForUser(userId)]); + if (!skipKfAuthSync) { + defer(async () => syncBanToKfAuth(userId)); + } + } + if (status === 'confirmed-not-spam' && previousStatus !== status && !skipKfAuthSync) { + defer(async () => syncUnbanToKfAuth(userId)); } return { spamTag: existingTag, user }; } @@ -109,6 +119,12 @@ export const upsertSpamTag = async (options: UpsertSpamTagOptions): Promise syncBanToKfAuth(userId)); + } + } + if (status === 'confirmed-not-spam' && !skipKfAuthSync) { + defer(async () => syncUnbanToKfAuth(userId)); } return { spamTag, user }; }; @@ -123,14 +139,18 @@ export const getSpamTagForUser = async (userId: string) => { return u.spamTag ?? null; }; -export const removeSpamTagFromUser = async (userId: string) => { +export const removeSpamTagFromUser = async (userId: string, skipKfAuthSync?: boolean) => { const spamTag = await getSpamTagForUser(userId); if (!spamTag) return; + const wasBanned = spamTag.status === 'confirmed-spam'; await User.update( { spamTagId: null }, { where: { id: userId }, limit: 1, individualHooks: false }, ); await spamTag.destroy(); + if (wasBanned && !skipKfAuthSync) { + defer(async () => syncUnbanToKfAuth(userId)); + } }; const communityInclude = [ diff --git a/server/utils/session.ts b/server/utils/session.ts index c266c683d9..4818e22616 100644 --- a/server/utils/session.ts +++ b/server/utils/session.ts @@ -16,3 +16,21 @@ export const deleteSessionsForUser = async (email: string): Promise => { `Deleted ${(result[1] as { rowCount: number }).rowCount} sessions for user ${email}`, ); }; + +/** + * Deletes the session(s) created from a specific kf-auth session. + * The OIDC callback stamps `kfSessionId` (the ID token's `sid` claim) + * onto the session, so a kf-auth `session.revoked` webhook can end + * exactly the local sessions that belonged to it. + */ +export const deleteSessionsByKfSessionId = async (kfSessionId: string): Promise => { + const result = await sequelize.query( + `DELETE FROM "Sessions" + WHERE "expires" > NOW() + AND (data::jsonb->>'kfSessionId') = :kfSessionId`, + { replacements: { kfSessionId } }, + ); + const count = (result[1] as { rowCount: number }).rowCount; + console.log(`Deleted ${count} sessions for kf-auth session ${kfSessionId}`); + return count; +}; diff --git a/stubstub/global/setup.ts b/stubstub/global/setup.ts index 17a4452412..274017e134 100644 --- a/stubstub/global/setup.ts +++ b/stubstub/global/setup.ts @@ -27,9 +27,7 @@ export default async () => { const dotenv = require('dotenv'); dotenv.config({ path: path.join(__dirname, '..', '..', 'infra', '.env.test') }); - console.log(process.env); const { env, refreshEnv } = await import('server/env'); - console.log(env); if (!process.env.DATABASE_URL) { console.log('\nSit tight while a local test database is created...');