diff --git a/.claude/skills/key-gaps/key_gaps.py b/.claude/skills/key-gaps/key_gaps.py index d5bdc8a..775f7ab 100755 --- a/.claude/skills/key-gaps/key_gaps.py +++ b/.claude/skills/key-gaps/key_gaps.py @@ -57,6 +57,10 @@ FEATURE_GROUPS = { DEPENDENT_OPTIONAL = { "THERMOGRAPH_DISCORD_WEATHER_CHANNEL": "THERMOGRAPH_DISCORD_BOT_TOKEN", "THERMOGRAPH_DISCORD_SUBSCRIPTION_CHANNEL": "THERMOGRAPH_DISCORD_BOT_TOKEN", + # Gateway-bot enable flag: truthy alone does nothing (web/app.py only starts the + # bot when discord_bot.enabled() sees the token too). One gateway connection per + # token — set in exactly one environment. + "THERMOGRAPH_DISCORD_BOT": "THERMOGRAPH_DISCORD_BOT_TOKEN", } # Standalone optional keys: reported present/absent, never a "gap" on their own. STANDALONE_OPTIONAL = [ diff --git a/deploy/secrets/prod.yaml b/deploy/secrets/prod.yaml index 4b777cd..af4aa27 100644 --- a/deploy/secrets/prod.yaml +++ b/deploy/secrets/prod.yaml @@ -22,6 +22,8 @@ THERMOGRAPH_DISCORD_CLIENT_SECRET: ENC[AES256_GCM,data:CrhrDfFmk7F2lWQeY9kd7yxzo THERMOGRAPH_DISCORD_APP_ID: ENC[AES256_GCM,data:lxwB08B143dCFsobG9JOkmScIQ==,iv:TFjzSDZWptqWgswiPHxJAzG1hlVI5bUA87ZKjBTsCGs=,tag:eRgvfiSS1Ujd5T3AeZCwUw==,type:str] THERMOGRAPH_DISCORD_BOT_TOKEN: ENC[AES256_GCM,data:zfVJLH8ddct2Jvstl/olZLQ9SM15ccWLCIpYe/k5BUZiV50atzpQfE13FifB1jWF6C+5P95odxVFtne7YJyaDxryfIX8Gbea,iv:wDM4qFpGYGtUJfEk5IbhMg9J9gr8ambEOkSWWBA2CSU=,tag:FhtUOe5WKMH2h7qIi4yKgQ==,type:str] REGISTRY_TOKEN: ENC[AES256_GCM,data:3VETZR026YXvWA7DLly4/mz+hqEK7vkEMwKlDKU6CQZeZiFpbQXWig==,iv:ixZJi2VWAZak6dFPvVyErVRanp9bzqXyV3MVa4QsBuU=,tag:Pc2Mdw58S0tSdkgJ5yuVNw==,type:str] +THERMOGRAPH_DISCORD_BOT: ENC[AES256_GCM,data:Kg==,iv:CPYN8aCu79PHaz3Zj6OgqyJhXdHLt0tLodgML2NuwQM=,tag:1B3IhlfjCwSlPq7FnKGeRg==,type:str] +THERMOGRAPH_DISCORD_WEATHER_CHANNEL: ENC[AES256_GCM,data:WIxYcoOnBDdDcNj8uJ5eUqXjVQ==,iv:l6kU5PGVcW2Nv7EqBUGCRxBzaJOJ3AW1nEEH33aAbmI=,tag:/KgdCKmrlQioIWdz21PcTg==,type:str] sops: age: - enc: | @@ -33,7 +35,7 @@ sops: PDXCB8EqKwdC3BnKlpD9ptYcuPHVUSgve1wIZYJ7iHIEhW9Kc6RXOw== -----END AGE ENCRYPTED FILE----- recipient: age1xx4dzs0dxlwvkv9sjuqzsphl7lfrxannkfken374yu2qvvcte9sqzktqt2 - lastmodified: "2026-07-22T03:17:22Z" - mac: ENC[AES256_GCM,data:e9mkAW/bib2yvx50FinJaDJe9dENkMmsW8sek072Gunh9+gh6rJZfYPZ+neo1a+B8T9I4WVMIraKl2fSbOCc4OPCxbxsNO/vemrlsF1RMl13aklxxAJqbl2TOL7zPv8c7gv6DaUxMYB2//UTnOurHiSa+LgEoexp8QM3C0yyICk=,iv:bsfkniozEHdZTKxNR+nrrxXXyCXKZz0Cc1D0EV0SPjY=,tag:G5YUWV0Et6X61HLVm7IJrA==,type:str] + lastmodified: "2026-07-23T04:33:06Z" + mac: ENC[AES256_GCM,data:BjNMEudsS9ZViR55OjSXu5qrOJ9yu2kCGx61qu4vE1ZZJIZtnnyZ3CfpsPygvLLhiFRj76xcqFnuSqTdr17BCEHz3UzsHFv0vBi17lZ5ksN5Oz+9wr+3Pg3TvxC0VF2VHJVP84VH61CmB5+G4WOms8WqLtmIGSLYcTVtcIFoUhk=,iv:jTEB8Mxg8qIyNfhpSgJtUvULVx4+XFrPLyQKhNcbkTg=,tag:SIyvNltdGCMfDGvi4kD3MA==,type:str] unencrypted_suffix: _unencrypted version: 3.13.2 diff --git a/deploy/thermograph.env.example b/deploy/thermograph.env.example index 3ad44cc..9b559f1 100644 --- a/deploy/thermograph.env.example +++ b/deploy/thermograph.env.example @@ -184,6 +184,13 @@ THERMOGRAPH_BASE_URL=https://thermograph.org # alone). Leave unset to disable. In the Thermograph.org server: # weather-events = 1529274516746932307 #THERMOGRAPH_DISCORD_WEATHER_CHANNEL= +# Discord gateway bot (@mention/DM grading): runs INSIDE the backend leader +# process (same singleton election as the notifier — see web/app.py's lifespan), +# riding its event loop; no separate bot process. Opt-in: any truthy value here +# starts it, provided BOT_TOKEN above is also set (flag alone is a silent no-op). +# Discord allows ONE gateway connection per bot token, so enable this in exactly +# one environment — prod, the only vault with the token. +#THERMOGRAPH_DISCORD_BOT= # Account linking (OAuth2 "identify"): lets a signed-in user connect their Discord # account, storing their Discord user id for DM alerts. CLIENT_ID is the same App # ID above. The CLIENT_SECRET is from OAuth2 -> Client Secret (a credential). In the