Conversation
Add except ban block for 172.16.0.0/12 (Docker bridge subnets) to prevent bridge and other internal containers from being G-Lined by DNSBL checks. Also fix antirandom except to use CIDR 172.16.0.0/12 instead of 172.17.* to cover all Docker bridge network subnets.
The test_sends_relaymsg_when_capability_negotiated test was not mocking cfg.irc_relaymsg_clean_nicks, causing it to pick up the env var from .env.dev (BRIDGE_RELAYMSG_CLEAN_NICKS=true) and skip the /d suffix. Now explicitly patches cfg to False, matching the companion clean_nick test.
Cross-reference audit of apps/unrealircd/config/unrealircd.conf.template against UnrealIRCd 6.x upstream example.conf and modules.default.conf. Covers: modules (A), TLS (B), set blocks (C), allow (D), listen (E), link (F), log (G), except ban (H), blacklist (I), oper (J), anti-flood/connthrottle (K), drpass (L), plaintext/outdated-tls (M), websocket (N), spamfilter/badwords (O), third-party modules (P). Findings: 3 critical, 8 warnings, 35+ OK, 12 suggestions.
Cross-reference audit of atheme.conf.template against upstream atheme.conf.example (master branch) covering all 16 audit categories. Key findings: - 2 CRITICAL: example operator left in config; orphaned chanfix block - 4 WARNING: debug loglevel, missing pbkdf2 v1 compat, duplicate scram ref - 35+ OK: vast majority matches or exceeds upstream - 8+ SUGGESTIONS: scram_mechanisms, exttarget modules, log separation
Critical fixes: - Add drpass block for /DIE and /RESTART protection (IRC_DRPASS env var) - Template WEBIRC password via ATL_WEBIRC_PASSWORD env var (was hardcoded) - Restrict admin oper mask from *@* to Docker network (172.16.0.0/12) - Require TLS for oper authentication (require-modes z) Warning fixes: - Add connthrottle config for connection throttling during attacks - Add spamfilter defaults (ban-time, ban-reason, virus-help-channel) - Add allow-user-stats to restrict sensitive stats to opers - Restrict link block incoming mask to Docker network + localhost - Restrict RPC user match to Docker network + localhost - Tighten connect-flood from 20:10 to 5:60 for production
Critical fixes:
- Remove insecure 'operator jilles' block (SRA to anyone with that nick)
- Comment out orphaned chanfix{} block (chanfix/main module not loaded)
Warning fixes:
- Reduce loglevel from debug to production-appropriate categories
- Remove duplicate commented saslserv/scram reference
From reading every page on the UnrealIRCd wiki (Set_block, Security, Configuration): - Add set::gline-address (was missing; only kline-address was set) - Add set::snomask-on-oper +bBcdfkqsSo (recommended default for full server notice visibility) - Add +H to modes-on-oper (hides oper idle time from non-opers) - Add restrict-commands for private-message and private-notice with 120s connect-delay for unidentified users (Security page recommendation to combat spam bots, exempts identified/webirc/reputation users)
Browsed every page on prosody.im/doc and modules.prosody.im, read the full config/security/certificates/ports/modules/storage/MAM/ file_share/MUC docs plus community module pages. Critical fixes: - .env.example: flip TLS/auth defaults to secure (c2s_require_encryption, s2s_require_encryption, s2s_secure_auth = true; unencrypted_plain_auth = false) - .env.dev.example: add insecure overrides for local dev (self-signed certs) - Uncomment global ssl block (protocol tlsv1_2+, strong ciphers, secp384r1) - Restrict http_status_allow_cidr from 0.0.0.0/0 to Docker network Warning fixes: - Disable legacyauth module (use SASL SCRAM-SHA-256 instead) - Enable dont_archive_namespaces to exclude typing indicators and Jingle Added: docs/audits/prosody-config-audit.md with full findings Note: luacheck warnings on Prosody globals (dont_archive_namespaces, https_ssl) are expected - these are valid Prosody config directives, not Lua standard globals.
Scanned all sources: .env.example, .env.dev.example, all compose files, config templates (UnrealIRCd, Atheme, Prosody, Bridge, The Lounge), scripts (init.sh, prepare-config.sh, cert-manager/run.sh), web app env, and bridge Python code. Comprehensive table with 150+ variables cross-referenced across 6 columns. Findings: - Category A: 37 orphaned vars (defined but never consumed) - Category B: 33 undefined vars (consumed but not in .env.example) - Category C: 6 inconsistency issues (XMPP port naming mismatch, etc.) - Category D: 12 hardcoded values that could be env vars - Category E: ~30 dead vars (PostgreSQL, Adminer, Nginx with no compose service) - Category F: 14 duplicate variable pairs Priority fixes: port naming mismatch, missing critical vars, dead service sections.
Full cross-reference audit of 150+ env vars across all sources (compose,
config templates, scripts, code). Changes:
Removed (orphaned/dead — no compose service or consumer):
- ATL_PROJECT_NAME, ATL_BASE_DOMAIN (never consumed)
- PROSODY_ENV (nothing reads it; ATL_ENVIRONMENT is the discriminator)
- ATHEME_UPLINK_SSL_PORT, ATHEME_LOG_LEVEL (not consumed by templates)
- THELOUNGE_DOMAIN (not consumed anywhere)
- ATHEME_CHANFIX_* (4 vars for commented-out module)
- PROSODY_ACCOUNT_DELETION_CONFIRMATION (consumed code is commented out)
- All POSTGRES_* vars (12 vars — no PostgreSQL compose service)
- All ADMINER_* vars (7 vars — no Adminer compose service)
- NGINX_HTTP_PORT, NGINX_HTTPS_PORT (no nginx compose service)
- ATL_SENTRY_DSN, ATL_INTERNAL_SECRET_IRC/XMPP (empty, never consumed)
Fixed (naming mismatch):
- Renamed XMPP_C2S_PORT → PROSODY_C2S_PORT (and S2S, HTTP, HTTPS) to
match what xmpp.yaml compose actually consumes. The old XMPP_* names
were silently ignored.
Fixed (broken interpolation):
- IRC_UNREAL_RPC_USER/PASSWORD: replaced ${WEBPANEL_RPC_USER} with
literal values. Docker Compose does not expand ${VAR} inside .env files.
Added (previously undefined but consumed):
- CLOUDFLARE_DNS_API_TOKEN (cert-manager)
- PROSODY_STORAGE (docker-entrypoint.sh)
- PROSODY_C2S_DIRECT_TLS_PORT, PROSODY_S2S_DIRECT_TLS_PORT, PROSODY_PROXY65_PORT
- TURN_SECRET, TURN_EXTERNAL_HOST
Reorganized:
- Clear section headers with 12-factor notes
- Portal-consumed vars separated with explicit comment
- Grouped by service lifecycle, not arbitrary categories
Added: docs/audits/env-var-audit.md with full 150+ var cross-reference
Critical fixes: - just prod/staging now run init.sh and pass --env-file .env (was bare docker compose with no init, no dirs, no config generation) - prepare-config.sh only sources .env.dev when ATL_ENVIRONMENT=dev, preventing dev overrides from leaking into prod config generation - Prosody .env.example cert paths changed from 'localhost' to 'atl.chat' (dev override in .env.dev correctly uses xmpp.localhost) Cleanup: - Removed meaningless --profile staging/prod from down commands (no services use these profiles; staging/prod are identical to default) Added: docs/audits/dev-prod-lifecycle-audit.md with full trace of both flows covering env, scripts, Docker, TLS, DNS, and networking
New: docs/deployment.md — comprehensive guide for deploying the atl.chat stack on Server B behind an Nginx Proxy Manager on Server A, connected via Tailscale mesh. Covers: - Full architecture diagram and prerequisites - Step-by-step Server B setup (.env configuration) - DNS records (A, CNAME, SRV for XMPP federation) - NPM proxy host config (HTTPS services: BOSH, WebSocket, Lounge, WebPanel) - NPM stream config (TCP passthrough: IRC TLS, XMPP C2S/S2S) - Certificate renewal and reload automation - Security checklist, backup strategy, troubleshooting Config changes: - Prosody: add Tailscale CIDR (100.64.0.0/10) to trusted_proxies - UnrealIRCd: add proxy 'npm-forwarded' block trusting Forwarded headers from gateway IP and Tailscale range Note: UnrealIRCd does not support HAProxy PROXY protocol on raw TCP listeners (upstream limitation). Direct IRC clients through NPM TCP streams appear as the proxy IP. Web clients use WEBIRC for real IPs.
Per the UnrealIRCd Proxy block wiki docs (pasted by user):
- Migrated old `webirc {}` block (pre-6.1.1 syntax) to new `proxy {}`
block with `type webirc` — we're on 6.2.0.1
- Changed `type forwarded` to `type x-forwarded` since NPM sends
X-Forwarded-For headers (not RFC 7239 Forwarded headers)
- Added clear doc comments explaining each proxy block's purpose
- Noted that x-forwarded/forwarded types auto-exempt matching hosts
from connect floods and blacklist checks (6.1.8+ feature)
- Updated deployment guide to explain the three real-IP mechanisms:
X-Forwarded-For (WebSocket), WEBIRC (web gateways), none (raw TCP)
Portal's mod_http_admin_api requires Bearer tokens (mod_tokenauth). This adds mod_http_oauth2 to enable OAuth2 token generation: - Added mod_http_oauth2 to modules.list (Prosody community module) - Enabled 'http_oauth2' and 'invites' in global modules_enabled - Configured OAuth2: password grant, 24h access tokens, 30d refresh - Added oauth2_registration_key for dynamic client registration Token generation flow for Portal: 1. Register client: POST /oauth2/register 2. Get token: POST /oauth2/token (grant_type=password, scope=prosody:operator) 3. Use token: Authorization: Bearer <token> Verified end-to-end: create user (200), get user, delete user (200).
|
Cursor Agent can help with this pull request. Just |
There was a problem hiding this comment.
Sorry @kzndotsh, your pull request is larger than the review limit of 150000 diff characters
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
|
Important Review skippedToo many files! This PR contains 220 files, which is 70 over the limit of 150. ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (220)
You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds OAuth2 to Prosody, tightens network ACLs and Docker subnet allowances, renames bridge identity from Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
There was a problem hiding this comment.
This PR significantly improves the development environment setup with comprehensive security hardening for IRC/XMPP services. However, critical security vulnerabilities must be addressed before merge.
Security Issues Requiring Fix:
- Hardcoded credentials in .env.example must not be deployed unchanged
- OAuth2 registration key needs secure default or required configuration
- Temporary file creation vulnerabilities enable privilege escalation attacks
The configuration improvements (TLS hardening, proper network isolation, OAuth2 integration) are well-implemented. Once the security issues are resolved, this will be ready to merge.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
| IRC_CLOAK_KEY_1=daa0ad2a69ba7683a2cdb02499f2e98b0729423bb7578d1f1dfbcdfe015f1f8b554b13203289c83D | ||
| IRC_CLOAK_KEY_2=899874eda706ee805bd34792bfd7bd62711f1938dea920c8bdf8396fe136ab6a83785a3ce54eB298 | ||
| IRC_CLOAK_KEY_3=d8936d8fff38eace5c379c94578abfa802088bd241329c64506513fe8e4de3e2304f7dd00355A8d6 | ||
| IRC_OPER_PASSWORD='$argon2id$v=19$m=6144,t=2,p=2$WXOLpTE+DPDr8q6OBVTx3w$bqXpBsaAK6lkXfR/IPn+TcE0VJEKjUFD7xordE6pFSo' | ||
| IRC_DRPASS=change_me_drpass | ||
| IRC_SERVICES_PASSWORD=change_me_secure_services_pass | ||
| ATL_WEBIRC_PASSWORD=change_me_webirc_password |
There was a problem hiding this comment.
🛑 Security Vulnerability: Production environment file contains hardcoded secrets and example credentials that must be changed before deployment. Multiple placeholder passwords use predictable patterns like "change_me_*" which creates security risk if deployed without modification.1
Footnotes
-
CWE-798: Use of Hard-coded Credentials - https://cwe.mitre.org/data/definitions/798.html ↩
apps/prosody/config/prosody.cfg.lua
Outdated
| oauth2_refresh_token_ttl = 2592000 -- 30 days | ||
| oauth2_require_code_challenge = false -- Portal uses password grant, not PKCE | ||
| -- Dynamic client registration (enables Portal to register as OAuth2 client) | ||
| oauth2_registration_key = Lua.os.getenv("PROSODY_OAUTH2_REGISTRATION_KEY") or "dev-oauth2-registration-key" |
There was a problem hiding this comment.
🛑 Security Vulnerability: OAuth2 registration key uses a weak default value "dev-oauth2-registration-key" that allows any client to register. This enables unauthorized access to the admin API if deployed to production without changing this value.1
| oauth2_registration_key = Lua.os.getenv("PROSODY_OAUTH2_REGISTRATION_KEY") or "dev-oauth2-registration-key" | |
| oauth2_registration_key = Lua.os.getenv("PROSODY_OAUTH2_REGISTRATION_KEY") or error("PROSODY_OAUTH2_REGISTRATION_KEY must be set") |
Footnotes
-
CWE-798: Use of Hard-coded Credentials - https://cwe.mitre.org/data/definitions/798.html ↩
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the development environment setup and hardens the IRC/XMPP stack configurations based on detailed security audits. It streamlines environment variable management, ensuring clearer separation between development and production settings. A new, comprehensive production deployment guide is also included, outlining the necessary steps for a robust and secure deployment. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request delivers a significant hardening and refactoring of the IRC/XMPP stack. The changes, well-documented through included audit reports, address critical security vulnerabilities in UnrealIRCd and Atheme, streamline environment variables for clarity and security, and fix the production deployment process. The addition of a detailed production deployment guide is a major improvement. Overall, these changes substantially enhance the project's security, maintainability, and operational readiness.
There was a problem hiding this comment.
3 issues found across 16 files
Confidence score: 3/5
AGENTS.mdadviseschmod 666on the Docker socket, which is a concrete security footgun; prefer docker group membership to avoid root-level access for any local user.justfileremoves thestagingcompose profile when bringing up staging, so staging-only services/configs may not start as expected.- Score reflects a few user-impacting risks (security guidance and staging/prosody behavior) rather than code-level breakage across the whole PR.
- Pay close attention to
AGENTS.md,justfile,apps/prosody/config/prosody.cfg.lua- security guidance and environment/profile behavior.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="AGENTS.md">
<violation number="1" location="AGENTS.md:92">
P1: Avoid instructing users to make the Docker socket world-writable. `chmod 666` allows any local user to gain root-level control via Docker. Prefer adding the user to the `docker` group and keeping the socket at 660.</violation>
</file>
<file name="apps/prosody/config/prosody.cfg.lua">
<violation number="1" location="apps/prosody/config/prosody.cfg.lua:448">
P2: CIDR `172.16.0.0/12` does not include localhost (`127.0.0.1`), contradicting the comment and potentially breaking any in-container health checks against the status endpoint. If localhost access is intended, add it explicitly.</violation>
</file>
<file name="justfile">
<violation number="1" location="justfile:43">
P2: Staging now starts without the `staging` compose profile, so staging-only services/config won’t be enabled. Keep the staging profile when bringing up the stack.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
|
||
| # Logging & Monitoring | ||
| # --- Logging --- |
There was a problem hiding this comment.
Bug: Changing XMPP_DOMAIN in .env without updating the hardcoded PROSODY_SSL_KEY and PROSODY_SSL_CERT paths will cause Prosody to fail on startup.
Severity: MEDIUM
Suggested Fix
Remove the explicit PROSODY_SSL_KEY and PROSODY_SSL_CERT variables from .env.example to allow Prosody's configuration to automatically derive the correct certificate paths from the PROSODY_DOMAIN. This removes the tight coupling and prevents configuration mismatches.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: .env.example#L235-L236
Potential issue: The `.env.example` file sets explicit paths for `PROSODY_SSL_KEY` and
`PROSODY_SSL_CERT` that are hardcoded to the `atl.chat` domain. However, the entrypoint
script generates certificates based on the `XMPP_DOMAIN` variable. If a user changes
`XMPP_DOMAIN` to a different value without also updating the `PROSODY_SSL_KEY` and
`PROSODY_SSL_CERT` paths, a mismatch will occur. This will cause Prosody to fail to
start because it cannot find the certificate files at the configured, now incorrect,
path.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (5)
apps/atheme/config/atheme.conf.template (1)
258-258: Avoid hardcoded line references in inline comments.“(line 174)” will drift on future edits. Prefer a stable reference without line numbers.
♻️ Suggested tweak
-/* saslserv/scram already loaded above in the SASL section (line 174) */ +/* saslserv/scram already loaded above in the SASL section */🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/atheme/config/atheme.conf.template` at line 258, Update the inline comment mentioning "saslserv/scram" to remove the hardcoded "(line 174)" and replace it with a stable reference such as "see the SASL section above" or "as noted in the SASL section" so future edits won't break the reference; locate the comment that currently reads "saslserv/scram already loaded above in the SASL section (line 174)" and edit it to reference the "SASL section" by name only (or add a nearby header/anchor comment "SASL section" if one doesn't exist) to provide a durable pointer.docs/deployment.md (1)
114-116: Avoidcurl | bashin production runbooks.Line 115 executes remote code directly. Prefer package-managed install or checksum/signature-verified download in production docs.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/deployment.md` around lines 114 - 116, The runbook currently pipes the remote install script directly into bash with the `curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin` pattern; change the guidance to avoid `curl | bash` by recommending package-managed installation if available (e.g., distro package or Homebrew), or instructing to download the installer to a temporary file, verify its checksum or signature against an authoritative source, and only then execute it (or extract/install manually) for the `just` installer; update the docs to include the exact alternative steps (download URL, checksum/signature verification step, and safe execution instructions) in place of the current piped command.docs/audits/prosody-config-audit.md (1)
206-214: Update summary table to reflect fixes applied in this PR.Several critical/warning items have been addressed by the configuration changes in this same PR:
- SSL block is now uncommented
legacyauthis disabledhttp_status_allow_cidris restrictedConsider updating the summary counts or adding a "Status: Fixed in this PR" note.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/audits/prosody-config-audit.md` around lines 206 - 214, Update the summary table to reflect the fixes applied in this PR: decrease the 🔴 CRITICAL count by 1 to remove the "global ssl block commented out" item (since the ssl block is now uncommented), decrease the 🟡 WARNING count by 2 to remove "legacyauth enabled" and the open `http_status_allow_cidr` item (since `legacyauth` is now disabled and `http_status_allow_cidr` is restricted), and optionally add a short "Status: Fixed in this PR" note next to those specific rows (reference `legacyauth`, `http_status_allow_cidr`, and the global ssl block) so readers can see these items were remediated rather than still outstanding.apps/unrealircd/config/unrealircd.conf.template (1)
778-782: Consider using separate passwords for restart and die.Using the same
IRC_DRPASSfor both/DIEand/RESTARTis acceptable but reduces defense-in-depth. If the password is compromised, both critical commands become accessible.💡 Optional: Use separate environment variables
drpass { - restart "${IRC_DRPASS}"; - die "${IRC_DRPASS}"; + restart "${IRC_DRPASS_RESTART}"; + die "${IRC_DRPASS_DIE}"; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/unrealircd/config/unrealircd.conf.template` around lines 778 - 782, The drpass block currently uses a single env var IRC_DRPASS for both restart and die; change it to use separate environment variables (e.g., IRC_RESTART_PASS for restart and IRC_DIE_PASS for die) so each command has its own credential, updating the drpass { restart ...; die ...; } entries accordingly and keeping IRC_DRPASS only as an optional fallback if needed; ensure the template references the new env names wherever drpass is configured.docs/audits/unrealircd-config-audit.md (1)
642-666: Update summary to reflect fixes applied in this PR.The summary shows 3 critical issues, but the actual config changes in this PR address all three:
- drpass block added (lines 778-782)
- WEBIRC password uses env var (line 375)
- Admin oper mask restricted (line 787)
Additionally, several warnings are addressed (connthrottle, spamfilter, oper-only-stats via allow-user-stats). Consider updating the summary or adding notes about which fixes were applied.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/audits/unrealircd-config-audit.md` around lines 642 - 666, Update the "Summary" section under "By Severity" and "Priority Fixes" to reflect that the three critical issues have been fixed in this PR: remove or decrement the "🔴 CRITICAL" count and delete or mark resolved the items "Missing `drpass` block", "admin oper `mask *@*`", and "hardcoded WEBIRC password"; instead list them as fixed and reference the changes that addressed them (the added drpass block, WEBIRC password switched to env var, and tightened admin oper mask). Also note the additional warnings that were addressed (add mentions that `set::connthrottle`, `set::spamfilter`, and `set::oper-only-stats` were added or that `allow-user-stats` was applied) and update the "Priority Fixes" list to remove or demote items already implemented. Ensure the table counts and the "Priority Fixes" bullets match the current state of the config changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.env.example:
- Around line 4-5: The top-level claim "No orphans" is inconsistent with the
Portal section; update the .env example wording so it no longer asserts every
variable is consumed in-repo unconditionally—either change the line containing
"No orphans" to a qualified statement like "Most variables are consumed by at
least one compose file, config template, script, or application; exceptions
(e.g., Portal vars) are documented below" or add a parenthetical noting that
Portal variables are external and not consumed by this monorepo (refer to the
"Portal" section). Ensure the new text clearly links to or references the Portal
section so readers understand the exception.
In `@AGENTS.md`:
- Line 92: Replace the unsafe `sudo chmod 666 /var/run/docker.sock` instruction
with a safer alternative: instruct users to add themselves to the `docker` group
(e.g., `usermod -aG docker $USER` and re-login) or, if temporary access is
needed, use `sudo` for Docker commands or change socket ownership to root:docker
with `sudo chown root:docker /var/run/docker.sock && sudo chmod 660
/var/run/docker.sock`; update the AGENTS.md line that currently references `sudo
chmod 666 /var/run/docker.sock` to one of these safer options and include a note
that adding users to the docker group requires a new login/session.
In `@apps/atheme/AUDIT_REPORT.md`:
- Around line 3-7: Update the audit document header to pin the exact audited
revision by adding the commit SHA (audited_commit: <sha>) and a remediation
snapshot identifier, and annotate each finding entry in AUDIT_REPORT.md with an
explicit remediation status (pre-remediation or post-remediation) and a
reference to the PR/commit that fixed it; specifically update the header fields
around "Date", "Local config", and "Upstream reference" to include the audited
commit and add a per-finding status column or inline tag for the findings that
were fixed in this PR (the entries noted as already changed) so readers can
clearly see pre/post remediation state and where fixes live.
In `@apps/atheme/config/atheme.conf.template`:
- Around line 791-793: The repo lacks a bootstrap for the first SRA which causes
operator lockout; add an automated seed or clear docs: implement one of the
following fixes—(A) in docker-entrypoint.sh detect if no SRA exists and run the
SOPER ADD command against the running IRCd (e.g., piping "SOPER ADD
$ATHEME_SRA_ACCOUNT sra" via nc to localhost:6667) after startup, or (B) add a
templated include file (e.g., sras.conf) that substitutes an ATHEME_SRA_ACCOUNT
env var and is included by atheme.conf.template, or (C) add a clear README
section with explicit manual first-boot steps to connect and run "/msg OperServ
SOPER ADD <account> sra"; reference SOPER ADD, ATHEME_SRA_ACCOUNT,
docker-entrypoint.sh, and sras.conf to locate where to implement the change.
In `@apps/prosody/config/prosody.cfg.lua`:
- Around line 916-918: The fallback feed URL in the feeds table (the feed entry
using Lua.os.getenv("PROSODY_FEED_URL") or "...") is incorrect; replace the
literal "https://[REDACTED].org/feed" with "https://allthingslinux.org/feed" so
the feed key uses the correct fallback when PROSODY_FEED_URL is not set.
- Around line 572-584: The config currently allows the insecure Resource Owner
Password Grant; remove "password" from the allowed_oauth2_grant_types table
(leaving "authorization_code" and "device_code"), enable PKCE by setting
oauth2_require_code_challenge = true so authorization_code uses PKCE, and ensure
oauth2_registration_key is not falling back to the hardcoded
"dev-oauth2-registration-key" in production (use
Lua.os.getenv("PROSODY_OAUTH2_REGISTRATION_KEY") only and fail or warn when
unset). Reference the symbols allowed_oauth2_grant_types,
oauth2_require_code_challenge, and oauth2_registration_key when making these
changes.
In `@docs/audits/env-var-audit.md`:
- Line 3: The audit file’s generated header ("Generated: 2026-02-26 | Scope:
Full 12-factor env var cleanup") and the recommendations block that calls out
env var issues must be clarified as either a pre-remediation snapshot or be
regenerated after the PR’s environment template changes; update that header and
the recommendations text to explicitly state “pre-remediation snapshot” (or
re-run generation so it reflects current state) and annotate which specific
findings are resolved by the PR’s updated environment template so operators
won’t be confused about which items remain to address.
In `@justfile`:
- Around line 57-65: The two just targets down-staging and down-prod run an
unscoped docker compose down and can tear down all services; update each target
(down-staging and down-prod) to pass an explicit project name (e.g., docker
compose -p staging down and docker compose -p prod down or use --project-name)
so the teardown is scoped to the intended environment, ensuring you reference
the same project name that your corresponding up/start targets use.
- Around line 41-50: The staging and prod targets in the Justfile must set
ATL_ENVIRONMENT explicitly to avoid using a stray value from .env; update the
staging target (symbol: staging) to set ATL_ENVIRONMENT=staging and the prod
target (symbol: prod) to set ATL_ENVIRONMENT=production before calling
./scripts/init.sh and docker compose so both the init script and Docker Compose
use the intended environment (e.g., export or prefix the two commands in each
target).
In `@scripts/prepare-config.sh`:
- Around line 59-60: The if-condition that decides to load .env.dev currently
uses a default value (${ATL_ENVIRONMENT:-dev}) which causes unset
ATL_ENVIRONMENT to behave as "dev"; update the conditional in
scripts/prepare-config.sh so it only loads .env.dev when ATL_ENVIRONMENT is
explicitly set to "dev" (e.g. use a check that does not default, like testing
"${ATL_ENVIRONMENT:-}" = "dev" or ensuring ATL_ENVIRONMENT is non-empty and
equals "dev"), keeping the existing file existence check for
$PROJECT_ROOT/.env.dev and the log_info call intact.
---
Nitpick comments:
In `@apps/atheme/config/atheme.conf.template`:
- Line 258: Update the inline comment mentioning "saslserv/scram" to remove the
hardcoded "(line 174)" and replace it with a stable reference such as "see the
SASL section above" or "as noted in the SASL section" so future edits won't
break the reference; locate the comment that currently reads "saslserv/scram
already loaded above in the SASL section (line 174)" and edit it to reference
the "SASL section" by name only (or add a nearby header/anchor comment "SASL
section" if one doesn't exist) to provide a durable pointer.
In `@apps/unrealircd/config/unrealircd.conf.template`:
- Around line 778-782: The drpass block currently uses a single env var
IRC_DRPASS for both restart and die; change it to use separate environment
variables (e.g., IRC_RESTART_PASS for restart and IRC_DIE_PASS for die) so each
command has its own credential, updating the drpass { restart ...; die ...; }
entries accordingly and keeping IRC_DRPASS only as an optional fallback if
needed; ensure the template references the new env names wherever drpass is
configured.
In `@docs/audits/prosody-config-audit.md`:
- Around line 206-214: Update the summary table to reflect the fixes applied in
this PR: decrease the 🔴 CRITICAL count by 1 to remove the "global ssl block
commented out" item (since the ssl block is now uncommented), decrease the 🟡
WARNING count by 2 to remove "legacyauth enabled" and the open
`http_status_allow_cidr` item (since `legacyauth` is now disabled and
`http_status_allow_cidr` is restricted), and optionally add a short "Status:
Fixed in this PR" note next to those specific rows (reference `legacyauth`,
`http_status_allow_cidr`, and the global ssl block) so readers can see these
items were remediated rather than still outstanding.
In `@docs/audits/unrealircd-config-audit.md`:
- Around line 642-666: Update the "Summary" section under "By Severity" and
"Priority Fixes" to reflect that the three critical issues have been fixed in
this PR: remove or decrement the "🔴 CRITICAL" count and delete or mark resolved
the items "Missing `drpass` block", "admin oper `mask *@*`", and "hardcoded
WEBIRC password"; instead list them as fixed and reference the changes that
addressed them (the added drpass block, WEBIRC password switched to env var, and
tightened admin oper mask). Also note the additional warnings that were
addressed (add mentions that `set::connthrottle`, `set::spamfilter`, and
`set::oper-only-stats` were added or that `allow-user-stats` was applied) and
update the "Priority Fixes" list to remove or demote items already implemented.
Ensure the table counts and the "Priority Fixes" bullets match the current state
of the config changes.
In `@docs/deployment.md`:
- Around line 114-116: The runbook currently pipes the remote install script
directly into bash with the `curl --proto '=https' --tlsv1.2 -sSf
https://just.systems/install.sh | bash -s -- --to /usr/local/bin` pattern;
change the guidance to avoid `curl | bash` by recommending package-managed
installation if available (e.g., distro package or Homebrew), or instructing to
download the installer to a temporary file, verify its checksum or signature
against an authoritative source, and only then execute it (or extract/install
manually) for the `just` installer; update the docs to include the exact
alternative steps (download URL, checksum/signature verification step, and safe
execution instructions) in place of the current piped command.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
.env.dev.example.env.exampleAGENTS.mdapps/atheme/AUDIT_REPORT.mdapps/atheme/config/atheme.conf.templateapps/bridge/tests/test_irc_client.pyapps/prosody/config/prosody.cfg.luaapps/prosody/modules.listapps/unrealircd/config/unrealircd.conf.templatedocs/audits/dev-prod-lifecycle-audit.mddocs/audits/env-var-audit.mddocs/audits/prosody-config-audit.mddocs/audits/unrealircd-config-audit.mddocs/deployment.mdjustfilescripts/prepare-config.sh
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Seer Code Review
- GitHub Check: cubic · AI code reviewer
- GitHub Check: Cloudflare Pages
🧰 Additional context used
🧬 Code graph analysis (2)
scripts/prepare-config.sh (1)
scripts/init.sh (1)
log_info(37-39)
apps/bridge/tests/test_irc_client.py (4)
apps/bridge/src/bridge/config/schema.py (1)
irc_relaymsg_clean_nicks(159-163)apps/bridge/tests/test_discord_adapter.py (1)
router(27-39)apps/bridge/src/bridge/gateway/router.py (1)
get_mapping_for_discord(97-102)apps/bridge/src/bridge/adapters/irc/client.py (1)
_send_message(552-607)
🪛 dotenv-linter (4.0.0)
.env.example
[warning] 12-12: [ValueWithoutQuotes] This value needs to be surrounded in quotes
(ValueWithoutQuotes)
[warning] 16-16: [UnorderedKey] The PGID key should go before the PUID key
(UnorderedKey)
[warning] 21-21: [UnorderedKey] The ATL_CHAT_IP key should go before the ATL_GATEWAY_IP key
(UnorderedKey)
[warning] 25-25: [UnorderedKey] The CLOUDFLARE_DNS_API_TOKEN key should go before the LETSENCRYPT_EMAIL key
(UnorderedKey)
[warning] 32-32: [UnorderedKey] The ATHEME_VERSION key should go before the UNREALIRCD_VERSION key
(UnorderedKey)
[warning] 37-37: [UnorderedKey] The IRC_NETWORK_NAME key should go before the IRC_ROOT_DOMAIN key
(UnorderedKey)
[warning] 38-38: [UnorderedKey] The IRC_CLOAK_PREFIX key should go before the IRC_DOMAIN key
(UnorderedKey)
[warning] 42-42: [UnorderedKey] The IRC_SERVER_PORT key should go before the IRC_TLS_PORT key
(UnorderedKey)
[warning] 43-43: [UnorderedKey] The IRC_RPC_PORT key should go before the IRC_SERVER_PORT key
(UnorderedKey)
[warning] 52-52: [UnorderedKey] The IRC_DRPASS key should go before the IRC_OPER_PASSWORD key
(UnorderedKey)
[warning] 54-54: [UnorderedKey] The ATL_WEBIRC_PASSWORD key should go before the IRC_CLOAK_KEY_1 key
(UnorderedKey)
[warning] 58-58: [UnorderedKey] The IRC_ADMIN_EMAIL key should go before the IRC_ADMIN_NAME key
(UnorderedKey)
[warning] 71-71: [UnorderedKey] The ATHEME_SERVER_NAME key should go before the IRC_SERVICES_SERVER key
(UnorderedKey)
[warning] 72-72: [UnorderedKey] The ATHEME_SERVER_DESC key should go before the ATHEME_SERVER_NAME key
(UnorderedKey)
[warning] 73-73: [UnorderedKey] The ATHEME_UPLINK_HOST key should go before the IRC_SERVICES_SERVER key
(UnorderedKey)
[warning] 74-74: [UnorderedKey] The ATHEME_UPLINK_PORT key should go before the IRC_SERVICES_SERVER key
(UnorderedKey)
[warning] 75-75: [UnorderedKey] The ATHEME_NUMERIC key should go before the ATHEME_SERVER_DESC key
(UnorderedKey)
[warning] 76-76: [UnorderedKey] The ATHEME_RECONTIME key should go before the ATHEME_SERVER_DESC key
(UnorderedKey)
[warning] 77-77: [UnorderedKey] The ATHEME_HTTPD_PORT key should go before the ATHEME_NUMERIC key
(UnorderedKey)
[warning] 173-173: [UnorderedKey] The WEBPANEL_RPC_PASSWORD key should go before the WEBPANEL_RPC_USER key
(UnorderedKey)
[warning] 178-178: [UnorderedKey] The THELOUNGE_DELETE_UPLOADS_AFTER_MINUTES key should go before the THELOUNGE_PORT key
(UnorderedKey)
[warning] 184-184: [UnorderedKey] The PROSODY_ADMIN_EMAIL key should go before the XMPP_DOMAIN key
(UnorderedKey)
[warning] 193-193: [UnorderedKey] The PROSODY_DB_NAME key should go before the PROSODY_DB_PORT key
(UnorderedKey)
[warning] 195-195: [UnorderedKey] The PROSODY_DB_PASSWORD key should go before the PROSODY_DB_PORT key
(UnorderedKey)
[warning] 201-201: [UnorderedKey] The PROSODY_HTTP_PORT key should go before the PROSODY_S2S_PORT key
(UnorderedKey)
[warning] 202-202: [UnorderedKey] The PROSODY_HTTPS_PORT key should go before the PROSODY_HTTP_PORT key
(UnorderedKey)
[warning] 203-203: [UnorderedKey] The PROSODY_C2S_DIRECT_TLS_PORT key should go before the PROSODY_C2S_PORT key
(UnorderedKey)
[warning] 204-204: [UnorderedKey] The PROSODY_S2S_DIRECT_TLS_PORT key should go before the PROSODY_S2S_PORT key
(UnorderedKey)
[warning] 205-205: [UnorderedKey] The PROSODY_PROXY65_PORT key should go before the PROSODY_S2S_DIRECT_TLS_PORT key
(UnorderedKey)
[warning] 209-209: [UnorderedKey] The TURNS_PORT key should go before the TURN_PORT key
(UnorderedKey)
[warning] 211-211: [UnorderedKey] The TURN_EXTERNAL_HOST key should go before the TURN_PORT key
(UnorderedKey)
[warning] 218-218: [UnorderedKey] The PROSODY_ALLOW_UNENCRYPTED_PLAIN_AUTH key should go before the PROSODY_C2S_REQUIRE_ENCRYPTION key
(UnorderedKey)
[warning] 219-219: [UnorderedKey] The PROSODY_MAX_CONNECTIONS_PER_IP key should go before the PROSODY_S2S_REQUIRE_ENCRYPTION key
(UnorderedKey)
[warning] 220-220: [UnorderedKey] The PROSODY_REGISTRATION_THROTTLE_MAX key should go before the PROSODY_S2S_REQUIRE_ENCRYPTION key
(UnorderedKey)
[warning] 221-221: [UnorderedKey] The PROSODY_REGISTRATION_THROTTLE_PERIOD key should go before the PROSODY_S2S_REQUIRE_ENCRYPTION key
(UnorderedKey)
[warning] 222-222: [UnorderedKey] The PROSODY_BLOCK_REGISTRATIONS_REQUIRE key should go before the PROSODY_C2S_REQUIRE_ENCRYPTION key
(UnorderedKey)
[warning] 229-229: [UnorderedKey] The PROSODY_PROXY_ADDRESS key should go before the PROSODY_UPLOAD_EXTERNAL_URL key
(UnorderedKey)
[warning] 234-234: [UnorderedKey] The PROSODY_SSL_CERT key should go before the PROSODY_SSL_KEY key
(UnorderedKey)
[warning] 240-240: [UnorderedKey] The PROSODY_OPENMETRICS_IP key should go before the PROSODY_STATISTICS key
(UnorderedKey)
[warning] 241-241: [UnorderedKey] The PROSODY_OPENMETRICS_CIDR key should go before the PROSODY_OPENMETRICS_IP key
(UnorderedKey)
[warning] 246-246: [UnorderedKey] The PROSODY_ARCHIVE_COMPRESSION key should go before the PROSODY_ARCHIVE_EXPIRES_AFTER key
(UnorderedKey)
[warning] 248-248: [UnorderedKey] The PROSODY_ARCHIVE_MAX_QUERY_RESULTS key should go before the PROSODY_ARCHIVE_POLICY key
(UnorderedKey)
[warning] 282-282: [UnorderedKey] The PROSODY_PUSH_MAX_DEVICES key should go before the PROSODY_PUSH_MAX_ERRORS key
(UnorderedKey)
[warning] 289-289: [UnorderedKey] The PROSODY_ACCOUNT_GRACE_PERIOD key should go before the PROSODY_ACCOUNT_INACTIVE_PERIOD key
(UnorderedKey)
[warning] 294-294: [UnorderedKey] The PROSODY_SERVER_DESCRIPTION key should go before the PROSODY_SERVER_NAME key
(UnorderedKey)
[warning] 298-298: [UnorderedKey] The LUA_GC_PAUSE key should go before the LUA_GC_STEP_SIZE key
(UnorderedKey)
[warning] 299-299: [UnorderedKey] The LUA_GC_SPEED key should go before the LUA_GC_STEP_SIZE key
(UnorderedKey)
[warning] 309-309: [UnorderedKey] The BRIDGE_DISCORD_CHANNEL_ID key should go before the BRIDGE_DISCORD_TOKEN key
(UnorderedKey)
[warning] 317-317: [UnorderedKey] The BRIDGE_XMPP_COMPONENT_PORT key should go before the BRIDGE_XMPP_COMPONENT_SECRET key
(UnorderedKey)
[warning] 339-339: [UnorderedKey] The IRC_UNREAL_RPC_PASSWORD key should go before the IRC_UNREAL_RPC_USER key
(UnorderedKey)
.env.dev.example
[warning] 69-69: [UnorderedKey] The PROSODY_ALLOW_UNENCRYPTED_PLAIN_AUTH key should go before the PROSODY_C2S_REQUIRE_ENCRYPTION key
(UnorderedKey)
🪛 LanguageTool
docs/audits/unrealircd-config-audit.md
[style] ~79-~79: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...nnel "#support"— reasonable choice. - 🟢 **OK** —cloak-keys` — properly source...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~80-~80: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...y sourced from environment variables. - 🟢 OK — hiddenhost-prefix — configur...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~81-~81: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...nfigurable via ${IRC_CLOAK_PREFIX}. - 🟢 OK — cloak-method ip — good choic...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~87-~87: Ensure spelling is correct
Context: ... modes-on-oper "+xws" — good. Ensures opers get cloaking + wallops + server notices...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~92-~92: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...message-time 10s— matches upstream. - 🟢 **OK** —oper-auto-join "#mod-chat"` —...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~93-~93: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...od-chat"— appropriate for team use. - 🟢 **OK** —hide-ulinesandshow-connec...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~192-~192: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...uration with explicit cert/key paths. - 🟢 OK — Port 6901 plaintext for server...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~243-~243: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...M maxsize — matches upstream example. - 🟢 OK — JSON log: ircd.json.log ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~244-~244: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...rovides machine-readable audit trail. - 🟢 OK — Source filters: Identical ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~245-~245: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ick.*) — consistent and appropriate. - 🟢 **OK** — Log path templated via ${IRC_...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~298-~298: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...kup URLs for users to check their IP. - 🟢 OK — Action gline is appropriate ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~359-~359: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...s (just channel override + relaymsg). - 🟢 OK — Password sourced from environm...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~369-~369: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...th 10m zline — reasonable protection. - 🟢 OK — Target flood protection: C...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~370-~370: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...rivate messages, notices, and tagmsg. - 🟢 OK — **Known vs unknown user differ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~519-~519: Ensure spelling is correct
Context: ...oling Fix: Review and update the badwords list to match your community standards,...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~539-~539: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...separator nofor clean bridge nicks. - 🟢 **OK** —metadata` limits are reasonab...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~621-~621: Use a hyphen to join words.
Context: ...ilarly, *admin* blocks "administrator" type nicks but also catches legitimate n...
(QB_NEW_EN_HYPHEN)
AGENTS.md
[grammar] ~87-~87: Use a hyphen to join words.
Context: ... README.md ## Cursor Cloud specific instructions ### System depend...
(QB_NEW_EN_HYPHEN)
apps/atheme/AUDIT_REPORT.md
[style] ~557-~557: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...alysis difficult and the file will grow very quickly. Combined with `serverinfo::loglevel = ...
(EN_WEAK_ADJECTIVE)
docs/audits/prosody-config-audit.md
[style] ~25-~25: To form a complete sentence, be sure to include a subject.
Context: ...docs state: - c2s_require_encryption should be true (default in Prosody). "Almo...
(MISSING_IT_THERE)
[style] ~26-~26: The double modal “requires encrypted” is nonstandard (only accepted in certain dialects). Consider “to be encrypted”.
Context: ... Prosody). "By default Prosody requires encrypted server-to-server connections." - `s2s_s...
(NEEDS_FIXED)
docs/audits/dev-prod-lifecycle-audit.md
[style] ~71-~71: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...just prodandjust stagingstart the exact same services asdocker compose up -d` (eve...
(EN_WORDINESS_PREMIUM_EXACT_SAME)
🔇 Additional comments (24)
apps/atheme/config/atheme.conf.template (2)
356-356: Good production loglevel hardening.Line 356 is a solid improvement over debug-all logging for default deployments.
451-464: ChanFix block is now safely non-active and self-documented.This removes the prior module/block mismatch risk and keeps enablement instructions clear.
.env.dev.example (1)
65-69: Dev-only Prosody overrides are scoped appropriately.This block is clear and aligned with localhost/self-signed development behavior.
apps/bridge/tests/test_irc_client.py (1)
448-467: Nice test hardening for RELAYMSG config behavior.Scoping
cfgpatching in this block makes the test deterministic and avoids relying on ambient global config..env.example (1)
215-218: Prosody auth/encryption defaults are correctly hardened.These defaults set a safer production baseline and align with the security-hardening objective.
apps/unrealircd/config/unrealircd.conf.template (4)
369-390: LGTM! Well-documented proxy blocks for reverse proxy integration.The new proxy blocks properly handle WEBIRC and X-Forwarded-For headers from Nginx Proxy Manager and Tailscale. The comments clearly explain the purpose and limitations (TCP streams don't support HAProxy PROXY protocol).
787-793: Good security hardening: oper mask restricted and TLS required.Restricting admin oper to Docker network (
172.16.0.0/12) and requiring TLS viarequire-modes "z"addresses the critical findings from the audit. This significantly reduces the attack surface for oper password brute-forcing.
893-915: Excellent addition of allow-user-stats, spamfilter, and connthrottle configuration.These blocks address the audit warnings about missing configurations:
allow-user-stats "kMp"restricts sensitive stats to opersspamfilterprovides global defaults for spam handlingconnthrottleprotects against connection floods with proper exemptions for identified users
971-972: Connection flood limit tightened appropriately for production.Changing
connect-floodfrom20:10to5:60(5 connections per 60 seconds per IP) is a significant security improvement that aligns with production best practices mentioned in the audit.apps/prosody/modules.list (1)
37-37: LGTM! OAuth2 module added to support Portal integration.This addition is consistent with the
http_oauth2module enablement inprosody.cfg.luaand the new OAuth2 configuration block.docs/audits/prosody-config-audit.md (3)
32-47: Audit finding appears addressed by changes in this PR.The audit flags the global
sslblock as commented out (lines 531-536), but the actualprosody.cfg.luain this PR shows thesslblock is now uncommented at lines 533-538. Consider updating this finding to reflect the fix.
49-59: Audit finding addressed: legacyauth now disabled.The actual
prosody.cfg.luashowslegacyauthis now commented out at line 17 with a note to use SASL instead. This matches the recommended fix. Consider updating the audit to mark this as resolved.
61-75: Audit finding addressed: http_status_allow_cidr now restricted.The actual
prosody.cfg.luashowshttp_status_allow_cidris now set to"172.16.0.0/12"at line 448, matching the recommended fix exactly. Consider updating the audit to mark this as resolved.docs/audits/dev-prod-lifecycle-audit.md (1)
1-283: Comprehensive and well-structured dev/prod lifecycle audit.This audit provides excellent documentation of the deployment flow gaps between dev and prod environments. The findings are clearly categorized by severity with actionable fix recommendations. The priority order at the end provides a clear remediation roadmap.
docs/audits/unrealircd-config-audit.md (4)
306-338: Audit finding addressed: admin oper mask now restricted.The actual
unrealircd.conf.templateshows the admin oper mask is now*@172.16.0.0/12(line 787) withrequire-modes "z"(line 792), addressing both the mask restriction and TLS requirement recommendations. Consider updating this finding to reflect the fix.
407-432: Audit finding addressed: drpass block now present.The actual
unrealircd.conf.templatenow includes a drpass block at lines 778-782 using${IRC_DRPASS}. Consider updating this finding to reflect the fix.
556-575: Audit finding addressed: WEBIRC password now uses environment variable.The actual
unrealircd.conf.templateshows the npm-webirc proxy block at lines 372-376 now usespassword "${ATL_WEBIRC_PASSWORD}";instead of a hardcoded placeholder. Consider updating this finding to reflect the fix.
577-591: Audit finding addressed: RPC user match now restricted.The actual
unrealircd.conf.templateshowsrpc-usermatch at line 815 is now{ ip 172.16.0.0/12; ip 127.0.0.0/8; }instead of{ ip *; }. Consider updating this finding to reflect the fix.apps/prosody/config/prosody.cfg.lua (6)
17-17: LGTM! Legacy authentication properly disabled.Commenting out
legacyauthand using SCRAM-SHA-256 SASL authentication is the correct security choice for a modern XMPP deployment.
67-67: LGTM! OAuth2 and invites modules properly enabled.The
http_oauth2module enables Bearer token generation for Portal integration, and theinvitesmodule is correctly noted as a dependency for bothmod_http_admin_apiandmod_http_oauth2.Also applies to: 77-77
200-204: Good addition: Archive namespace exclusions reduce storage overhead.Excluding chat state notifications (typing indicators) and Jingle call signaling from the message archive is a sensible optimization that reduces database growth without losing important message content.
533-538: LGTM! Global SSL block enabled with strong TLS settings.TLS 1.2+ with strong ECDHE ciphers and proper options (
cipher_server_preference,single_dh_use,single_ecdh_use) addresses the audit's critical finding about the commented-out SSL block.
447-448: LGTM! HTTP status endpoint properly restricted.Restricting
http_status_allow_cidrto"172.16.0.0/12"(Docker network) addresses the audit finding about the world-open status endpoint.
388-389: LGTM! Trusted proxies expanded for Tailscale support.Adding
100.64.0.0/10(Tailscale CGNAT range) totrusted_proxiesenables proper X-Forwarded-For handling for Tailscale-proxied connections.
apps/atheme/AUDIT_REPORT.md
Outdated
| **Date:** 2026-02-26 | ||
| **Local config:** `apps/atheme/config/atheme.conf.template` | ||
| **Upstream reference:** Atheme `master` branch — `dist/atheme.conf.example` | ||
| **Upstream modules:** `modules/` directory tree | ||
|
|
There was a problem hiding this comment.
Pin the audit to an exact revision and remediation status.
This report reads as current-state, but several findings are already fixed in this PR (for example: Line 32–40, Line 257–280, Line 327–349). Without an explicit audited commit/snapshot and “pre/post remediation” status, the doc is misleading for operations and security triage.
📝 Proposed doc hardening
-**Date:** 2026-02-26
-**Local config:** `apps/atheme/config/atheme.conf.template`
+**Date:** 2026-02-26
+**Audit target commit:** `<commit_sha_audited>`
+**Local config:** `apps/atheme/config/atheme.conf.template`
+**Report scope:** Pre-remediation findings
+**Remediation status:** Some findings in this report are already addressed in PR `#6`; treat this document as an audit snapshot, not live state.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| **Date:** 2026-02-26 | |
| **Local config:** `apps/atheme/config/atheme.conf.template` | |
| **Upstream reference:** Atheme `master` branch — `dist/atheme.conf.example` | |
| **Upstream modules:** `modules/` directory tree | |
| **Date:** 2026-02-26 | |
| **Audit target commit:** `<commit_sha_audited>` | |
| **Local config:** `apps/atheme/config/atheme.conf.template` | |
| **Report scope:** Pre-remediation findings | |
| **Remediation status:** Some findings in this report are already addressed in PR `#6`; treat this document as an audit snapshot, not live state. | |
| **Upstream reference:** Atheme `master` branch — `dist/atheme.conf.example` | |
| **Upstream modules:** `modules/` directory tree |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/atheme/AUDIT_REPORT.md` around lines 3 - 7, Update the audit document
header to pin the exact audited revision by adding the commit SHA
(audited_commit: <sha>) and a remediation snapshot identifier, and annotate each
finding entry in AUDIT_REPORT.md with an explicit remediation status
(pre-remediation or post-remediation) and a reference to the PR/commit that
fixed it; specifically update the header fields around "Date", "Local config",
and "Upstream reference" to include the audited commit and add a per-finding
status column or inline tag for the findings that were fixed in this PR (the
entries noted as already changed) so readers can clearly see pre/post
remediation state and where fixes live.
docs/audits/env-var-audit.md
Outdated
| @@ -0,0 +1,513 @@ | |||
| # Environment Variable Audit — atl.chat Monorepo | |||
|
|
|||
| > Generated: 2026-02-26 | Scope: Full 12-factor env var cleanup | |||
There was a problem hiding this comment.
Clarify this as a pre-remediation snapshot or regenerate after applied fixes.
The recommendations in Lines 499-507 read as current-state issues, but parts of them are already addressed by this PR’s updated environment template, which can confuse operators.
Also applies to: 499-507
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/audits/env-var-audit.md` at line 3, The audit file’s generated header
("Generated: 2026-02-26 | Scope: Full 12-factor env var cleanup") and the
recommendations block that calls out env var issues must be clarified as either
a pre-remediation snapshot or be regenerated after the PR’s environment template
changes; update that header and the recommendations text to explicitly state
“pre-remediation snapshot” (or re-run generation so it reflects current state)
and annotate which specific findings are resolved by the PR’s updated
environment template so operators won’t be confused about which items remain to
address.
justfile
Outdated
| @echo "Initializing Staging Environment..." | ||
| ./scripts/init.sh | ||
| docker compose --env-file .env up -d | ||
|
|
||
| # Spin up the production stack (default profile) | ||
| # Spin up the production stack | ||
| [group('Orchestration')] | ||
| prod: | ||
| docker compose --profile prod up -d | ||
| @echo "Initializing Production Environment..." | ||
| ./scripts/init.sh | ||
| docker compose --env-file .env up -d |
There was a problem hiding this comment.
Set ATL_ENVIRONMENT explicitly in staging and prod targets.
These targets currently depend on whatever is in .env; if it is left as dev, initialization can apply dev behavior.
✅ Target-scoped environment fix
staging:
`@echo` "Initializing Staging Environment..."
- ./scripts/init.sh
- docker compose --env-file .env up -d
+ ATL_ENVIRONMENT=staging ./scripts/init.sh
+ ATL_ENVIRONMENT=staging docker compose --env-file .env up -d
prod:
`@echo` "Initializing Production Environment..."
- ./scripts/init.sh
- docker compose --env-file .env up -d
+ ATL_ENVIRONMENT=prod ./scripts/init.sh
+ ATL_ENVIRONMENT=prod docker compose --env-file .env up -d📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @echo "Initializing Staging Environment..." | |
| ./scripts/init.sh | |
| docker compose --env-file .env up -d | |
| # Spin up the production stack (default profile) | |
| # Spin up the production stack | |
| [group('Orchestration')] | |
| prod: | |
| docker compose --profile prod up -d | |
| @echo "Initializing Production Environment..." | |
| ./scripts/init.sh | |
| docker compose --env-file .env up -d | |
| `@echo` "Initializing Staging Environment..." | |
| ATL_ENVIRONMENT=staging ./scripts/init.sh | |
| ATL_ENVIRONMENT=staging docker compose --env-file .env up -d | |
| # Spin up the production stack | |
| [group('Orchestration')] | |
| prod: | |
| `@echo` "Initializing Production Environment..." | |
| ATL_ENVIRONMENT=prod ./scripts/init.sh | |
| ATL_ENVIRONMENT=prod docker compose --env-file .env up -d |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@justfile` around lines 41 - 50, The staging and prod targets in the Justfile
must set ATL_ENVIRONMENT explicitly to avoid using a stray value from .env;
update the staging target (symbol: staging) to set ATL_ENVIRONMENT=staging and
the prod target (symbol: prod) to set ATL_ENVIRONMENT=production before calling
./scripts/init.sh and docker compose so both the init script and Docker Compose
use the intended environment (e.g., export or prefix the two commands in each
target).
…ency across the codebase
|
|
|
|
||
| depends_on: | ||
| atl-irc-server: | ||
| condition: service_healthy | ||
|
|
||
| volumes: | ||
| - ../../data/irc/webpanel-data:/var/www/html/unrealircd-webpanel/data | ||
| - ../../data/irc/webpanel-data:/var/www/html/data |
There was a problem hiding this comment.
Bug: The nginx.conf root directive points to /var/www/html/unrealircd-webpanel/, but the refactored code now places files in /var/www/html/, which will cause 404 errors.
Severity: CRITICAL
Suggested Fix
Update the root directive in the nginx.conf file to point to the correct directory: root /var/www/html;. This will align the Nginx configuration with the updated file structure in the container.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: infra/compose/irc.yaml#L154
Potential issue: A refactoring flattened the web panel's directory structure, placing
application files in `/var/www/html/`. However, the `nginx.conf` file was not updated
and still specifies `root /var/www/html/unrealircd-webpanel;`. This mismatch will cause
Nginx to look for files in the wrong location, resulting in 404 errors and rendering the
web panel completely non-functional. The `Containerfile`, volume mounts in
`compose/irc.yaml`, and documentation in `AGENTS.md` all reflect the new, flattened
structure, but the Nginx configuration is out of sync.
There was a problem hiding this comment.
4 issues found across 39 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/unrealircd/docker-entrypoint.sh">
<violation number="1" location="apps/unrealircd/docker-entrypoint.sh:14">
P2: Keep creating/chowning the compiled LOGDIR so UnrealIRCd always has a writable log directory at startup. Omitting it can leave LOGDIR missing or owned by root when the container runs with non-root UID/GID.</violation>
</file>
<file name="apps/docs/content/docs/operations/monitoring.mdx">
<violation number="1" location="apps/docs/content/docs/operations/monitoring.mdx:99">
P3: The text claims all services log to stdout/stderr, but the table still documents The Lounge logs under `/var/opt/thelounge/` on the host. This is contradictory and can mislead operators. Consider narrowing the statement to only the services that log to stdout or calling out the exception explicitly.</violation>
</file>
<file name="AGENTS.md">
<violation number="1" location="AGENTS.md:83">
P3: The docs-old/AGENTS.md reference points to a non-existent directory/file, so the link in the Related section is broken and the documentation structure is misleading. Remove the docs-old reference or add the directory/file so the link is valid.</violation>
</file>
<file name="apps/bridge/Containerfile">
<violation number="1" location="apps/bridge/Containerfile:79">
P2: The healthcheck pattern doesn’t match the actual bridge process command line, so the container will be marked unhealthy even when the service is running.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
|
||
| # Create directories with proper ownership | ||
| mkdir -p /home/unrealircd/unrealircd/data /home/unrealircd/unrealircd/logs /home/unrealircd/unrealircd/tmp | ||
| mkdir -p /home/unrealircd/unrealircd/data /home/unrealircd/unrealircd/tmp |
There was a problem hiding this comment.
P2: Keep creating/chowning the compiled LOGDIR so UnrealIRCd always has a writable log directory at startup. Omitting it can leave LOGDIR missing or owned by root when the container runs with non-root UID/GID.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/unrealircd/docker-entrypoint.sh, line 14:
<comment>Keep creating/chowning the compiled LOGDIR so UnrealIRCd always has a writable log directory at startup. Omitting it can leave LOGDIR missing or owned by root when the container runs with non-root UID/GID.</comment>
<file context>
@@ -11,10 +11,10 @@ USER_ID=${PUID:-1000}
# Create directories with proper ownership
-mkdir -p /home/unrealircd/unrealircd/data /home/unrealircd/unrealircd/logs /home/unrealircd/unrealircd/tmp
+mkdir -p /home/unrealircd/unrealircd/data /home/unrealircd/unrealircd/tmp
# Fix ownership of directories (important for rootless Docker)
</file context>
…meouts Pin actions to specific commit hashes for increased security and reproducibility, ensuring that the exact version of the action is used consistently. Add timeout settings to various jobs to prevent them from running indefinitely, which helps in managing resources and avoiding unnecessary costs. These changes enhance the reliability and security of the CI/CD pipeline by ensuring consistent behavior and preventing potential disruptions.
…o lint dependencies Add "hypothesis" to the test dependencies to enable property-based testing, which can help uncover edge cases and improve test coverage. Include "ruff" in the lint dependencies to enforce code style and quality checks. Update the default-groups to include "lint" to ensure linting is part of the default development workflow.
…management Introduce a Renovate configuration file to automate dependency updates. This setup follows best practices and semantic commit conventions, ensuring dependencies are updated efficiently and securely. It includes rules for different types of updates, such as major, minor, and patch, and automates merging for non-breaking changes. This change aims to reduce manual effort in maintaining dependencies and improve overall project security and stability by keeping dependencies up-to-date.
Remove the nginx.conf file from the webpanel application. This change is likely due to a shift in deployment strategy or configuration management, possibly moving to a different web server setup or centralizing configuration elsewhere. This helps in reducing redundancy and potential configuration drift.
|
| destination { | ||
| file "${IRC_LOG_PATH}/ircd.log" { maxsize 100M; } | ||
| } | ||
| vhost "${DOLLAR}account@${IRC_ROOT_DOMAIN}"; |
There was a problem hiding this comment.
Bug: The prepare-config.sh script lacks a fallback for the new IRC_ROOT_DOMAIN variable, causing config generation to fail for existing deployments that don't have it in their .env file.
Severity: HIGH
Suggested Fix
In scripts/prepare-config.sh, add a default fallback value for the IRC_ROOT_DOMAIN variable, similar to how other variables are handled. For example: export IRC_ROOT_DOMAIN="${IRC_ROOT_DOMAIN:-atl.chat}". This ensures that the configuration remains valid even if the variable is not explicitly set in the user's .env file.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: apps/unrealircd/config/unrealircd.conf.template#L852
Potential issue: The configuration template `unrealircd.conf.template` now uses the
`${IRC_ROOT_DOMAIN}` variable. However, the `prepare-config.sh` script, which uses
`envsubst` to generate the final config, does not provide a default value for this new
variable. For existing deployments upgrading with older `.env` files that lack
`IRC_ROOT_DOMAIN}`, the variable will be replaced with an empty string. This results in
an invalid configuration line `vhost "$account@";`, which causes the UnrealIRCd server
to fail during startup due to a configuration validation error.
Remove the 'docs-old' directory from the documentation as it contains legacy documents that are no longer relevant. This change helps in cleaning up the documentation and prevents confusion by eliminating references to outdated materials.
The HEALTHCHECK command is updated to reflect the new process name "bridge --config" instead of "bridge.__main__". This change ensures that the health check accurately verifies the running state of the application, preventing false negatives and improving reliability.
Update the documentation to specify that while most services log to stdout/stderr, The Lounge service logs to files under a specific directory. This distinction is important for users to understand where to find logs for The Lounge, as it deviates from the standard logging behavior of other services.
…mproved flexibility Replace the luizm/action-sh-checker with pre-commit/action to leverage the pre-commit framework, which provides a more flexible and extensible way to manage shell linting. This change allows the use of additional arguments like `shellcheck` and `shfmt` for comprehensive linting and formatting checks. The removal of the `GITHUB_TOKEN` is due to the new action not requiring it for its operation.
…larity Separate the shellcheck and shfmt commands into individual steps in the GitHub Actions workflow. This change improves the readability and maintainability of the workflow by clearly delineating the different linting tasks. It also aligns with best practices for structuring workflows, making it easier to identify and troubleshoot issues with specific linting tools.
| healthcheck: | ||
| test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] | ||
| test: ["CMD", "pgrep", "-f", "bridge.__main__"] | ||
| interval: 30s | ||
| timeout: 10s |
There was a problem hiding this comment.
Bug: The healthcheck in infra/compose/bridge.yaml checks for bridge.__main__, but the container process is bridge --config. This will cause the health check to consistently fail.
Severity: HIGH
Suggested Fix
Update the healthcheck.test command in infra/compose/bridge.yaml to match the HEALTHCHECK command in the Containerfile. Change the test to correctly identify the running process, for example by using pgrep -f "bridge --config".
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: infra/compose/bridge.yaml#L58-L61
Potential issue: The `healthcheck` configuration in `infra/compose/bridge.yaml`
overrides the `HEALTHCHECK` instruction from the `Containerfile`. The compose file's
check (`pgrep -f "bridge.__main__"`) is outdated and does not match the container's
actual command (`bridge --config ...`). As a result, the health check will always fail
when using Docker Compose, marking the container as unhealthy even if the application is
running correctly. This will cause services that depend on the bridge's health
(`depends_on: service_healthy`) to fail to start.
Include the setup-python action to ensure that Python 3.11 is available when running shellcheck for shell scripts. This change is necessary because some shell scripts may rely on Python, and having a specific Python version ensures consistency and avoids potential issues with different Python versions across environments.
…test The smoke test step in the Docker workflow now uses the --entrypoint flag to explicitly set the entrypoint to echo. This change ensures that the echo command runs correctly, regardless of the default entrypoint defined in the Docker image. This makes the smoke test more reliable and prevents potential issues if the image's entrypoint changes.
Introduce a .gitignore file to the web app to prevent committing unnecessary files and directories. This includes build outputs (.next/, out/, dist/), dependencies (node_modules/), and environment files (.env, .env.*) while allowing .env.example for reference. This helps maintain a clean repository by excluding files that are not needed in version control.
Convert all indentation from spaces to tabs across multiple files to maintain consistency in the codebase. This change improves readability and ensures uniformity in the project's coding style.
…aks-action Include the GITLEAKS_LICENSE environment variable to ensure that the Gitleaks action can access the necessary license information. This change is essential for compliance and to enable the security workflow to function correctly with licensed features of Gitleaks.
…rity Inheriting secrets in the security workflow ensures that sensitive information is securely passed to the workflow, maintaining the integrity and confidentiality of the data. This change enhances the security posture of the CI/CD pipeline by ensuring that secrets are available where needed without hardcoding them.
| HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ | ||
| CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1 |
There was a problem hiding this comment.
Bug: The webpanel container's HEALTHCHECK will always fail because it uses wget, which is not installed in the image.
Severity: CRITICAL
Suggested Fix
Install wget in the Containerfile by adding RUN apk add --no-cache wget, or alternatively, replace the wget command in the HEALTHCHECK with curl, which is already available in the image.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: apps/webpanel/Containerfile#L43-L44
Potential issue: The `HEALTHCHECK` instruction added to the `webpanel/Containerfile`
uses the `wget` command to check the application's status. However, the base image
`trafex/php-nginx:3.10.0` does not include `wget`, and it is not installed in any
subsequent layer. This will cause the health check to fail every time it runs because
the `wget` command is not found. Consequently, container orchestration systems will
report the container as "unhealthy" even if the application is running correctly, which
will impact monitoring, alerting, and any automated actions based on container health
status.
Change the XMPP component port from 5222 to 5347 in the architecture diagram to reflect the correct configuration. docs(environment-variables): add new logging and relay/media variables Introduce `LOG_MAX_SIZE` and `LOG_MAX_FILES` for log rotation configuration, enhancing log management. Add `ATHEME_SRA_BOOTSTRAP_ACCOUNT` for initial SRA setup. Include `BRIDGE_IRC_TLS_VERIFY` for TLS certificate verification settings. Add relay and media variables `BRIDGE_RELAYMSG_CLEAN_NICKS`, `XMPP_AVATAR_BASE_URL`, and `XMPP_UPLOAD_FETCH_URL` to improve configuration flexibility. docs(bridge/configuration): update Portal base URL Change `BRIDGE_PORTAL_BASE_URL` to use the new domain `https://portal.atl.tools` for consistency with updated service endpoints.
|
🎉 This PR is included in version 1.0.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
No description provided.