-
Notifications
You must be signed in to change notification settings - Fork 3
Feature user service refactoring #94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add MCP protocol types with JSON-RPC 2.0 support - Implement WebSocket handler with heartbeat mechanism - Create tool registry with pluggable handler architecture - Add session management for conversation context - Register /mcp WebSocket endpoint with OAuth auth - Add Casbin rules for group_user and group_admin access - Include comprehensive unit tests for protocol layer Components: - src/mcp/protocol.rs: JSON-RPC 2.0 + MCP types - src/mcp/websocket.rs: Actix WebSocket actor - src/mcp/registry.rs: Tool handler infrastructure - src/mcp/session.rs: Session state management - migrations/20251227140000: Casbin authorization rules Dependencies: - actix 0.13.5 (WebSocket actor framework) - actix-web-actors 4.3.1 (Actix-web WS integration) - async-trait 0.1.77 (Tool handler trait) Supports: - initialize, tools/list, tools/call methods - OAuth bearer token authentication - Casbin role-based authorization - Structured logging with tracing - Graceful connection handling
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 24149610 | Triggered | Bearer Token | bd423f5 | src/connectors/admin_service/jwt.rs | View secret |
| 25120004 | Triggered | Hashicorp Vault Token | 1f483ee | config-to-validate.yaml | View secret |
| 9658888 | Triggered | Generic Password | 0a5afab | config-to-validate.yaml | View secret |
| 26598182 | Triggered | influxdb_token | 16b5a2a | src/project_app/tests.rs | View secret |
| 25120005 | Triggered | Generic High Entropy Secret | 1f483ee | config-to-validate.yaml | View secret |
| 25120006 | Triggered | Generic High Entropy Secret | 0a5afab | test_agent_report.sh | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secrets safely. Learn here the best practices.
- Revoke and rotate these secrets.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request implements a comprehensive user service refactoring that adds external service connectors, enhances configuration management, and improves deployment workflows.
Changes:
- Introduced a new
connectorsmodule with User Service, Docker Hub, Install Service, and Admin Service integrations - Simplified database delete operations by removing unnecessary transactions
- Added configuration versioning and deployment settings with environment variable support
- Enhanced CI/CD workflows with multi-platform builds and improved caching
Reviewed changes
Copilot reviewed 134 out of 344 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/db/project.rs | Simplified delete operation by removing transaction overhead |
| src/db/cloud.rs | Simplified delete operation by removing transaction overhead |
| src/db/agreement.rs | Simplified delete operation by removing transaction overhead |
| src/db/deployment.rs | Added new fetch methods for deployment lookup by hash and project |
| src/db/command.rs | Enhanced command fetching with new methods for ID and command_id lookup |
| src/connectors/* | New connector infrastructure for external service integrations |
| src/configuration.rs | Added comprehensive configuration with defaults and environment overrides |
| Cargo.toml | Updated dependencies for connectors and async operations |
| .github/workflows/* | Enhanced CI/CD with multi-platform builds and improved caching |
Files not reviewed (88)
- .sqlx/query-0bb6c35cba6f3c5573cf45c42b93709286b2a50446caa2a609aaf77af12b30bb.json: Language not supported
- .sqlx/query-0dab58aa1022e2c1f4320f232195f54d89279057657c92305f606522fa142cf7.json: Language not supported
- .sqlx/query-0f9023a3cea267596e9f99b3887012242345a8b4e4f9d838dc6d44cc34a89433.json: Language not supported
- .sqlx/query-0faf1a2932ba1b37fc9f982bc86c323869489c6dc7e17479b647f0aa799df910.json: Language not supported
- .sqlx/query-172dbb0c3947fa99e8522510096cd8dbfd785bb982a0622d3c05afb2ab3e260f.json: Language not supported
- .sqlx/query-17f59e9f273d48aaf85b09c227f298f6d6f6f231554d80ed621076157af7f80a.json: Language not supported
- .sqlx/query-1cabd2f674da323da9e0da724d3bcfe5f968b31500e8c8cf97fe16814bc04164.json: Language not supported
- .sqlx/query-1f1b8182d59d8253662da0ea73b69b6857e5f3c8f4292ba9c4491e062591575b.json: Language not supported
- .sqlx/query-1f299262f01a2c9d2ee94079a12766573c91b2775a086c65bc9a5fdc91300bb0.json: Language not supported
- .sqlx/query-24876462291b90324dfe3682e9f36247a328db780a48da47c9402e1d3ebd80c9.json: Language not supported
- .sqlx/query-2872b56bbc5bed96b1a303bf9cf44610fb79a1b9330730c65953f0c1b88c2a53.json: Language not supported
- .sqlx/query-2c7065ccf4a0a527087754db39a2077a054026cb2bc0c010aba218506e76110f.json: Language not supported
- .sqlx/query-309c79e9f4b28e19488e71ca49974e0c9173f355d69459333acf181ff2a82a1c.json: Language not supported
- .sqlx/query-327394e1777395afda4a1f6c1ca07431de81f886f6a8d6e0fbcd7b6633d30b98.json: Language not supported
- .sqlx/query-32d118e607db4364979c52831e0c30a215779928a041ef51e93383e93288aac2.json: Language not supported
- .sqlx/query-36f6c8ba5c553e6c13d0041482910bc38e48635c4df0c73c211d345a26cccf4e.json: Language not supported
- .sqlx/query-39d0d9c946cbd9cdacff0d59a39a6c331091879a27faeabbebf1602c797b22ea.json: Language not supported
- .sqlx/query-3b6ec5ef58cb3b234d8c8d45641339d172624d59fff7494f1929c8fe37f564a4.json: Language not supported
- .sqlx/query-3dd9013b8856be2d991a656c3cdd77692bd1a336be4d06ff6e0ac6831164617e.json: Language not supported
- .sqlx/query-3efacedb58ab13dad5eeaa4454a4d82beb1dedc0f62405d008f18045df981277.json: Language not supported
- .sqlx/query-41edb5195e8e68b8c80c8412f5bb93cf4838bd1e7e668dafd0fffbd13c90d5aa.json: Language not supported
- .sqlx/query-438ee38e669be96e562d09d3bc5806b4c78b7aa2a9609c4eccb941c7dff7b107.json: Language not supported
- .sqlx/query-467365894a7f9a0888584e8879cac289299f4d03539b9c746324cd183e265553.json: Language not supported
- .sqlx/query-4acfe0086a593b08177791bb3b47cb75a999041a3eb6a8f8177bebfa3c30d56f.json: Language not supported
- .sqlx/query-4bdcd8d475ffd8aab728ec2b9d0d8c578770e2d52bf531de6e69561a4adbb21c.json: Language not supported
- .sqlx/query-4e375cca55b0f106578474e5736094044e237999123952be7c78b46c937b8778.json: Language not supported
- .sqlx/query-4e7b82d256f7298564f46af6a45b89853785c32a5f83cb0b25609329c760428a.json: Language not supported
- .sqlx/query-4ed4ce17b28e36898d9afabb96b7043ceee664f67752c41bf06df6e51ed69362.json: Language not supported
- .sqlx/query-4f54a93856a693345a9f63552dabf3192c3108a2776bb56f36787af3fa884554.json: Language not supported
- .sqlx/query-4fbb395f2080f29291ea091d2c4135b962e41b4e5b49d20e9d5fee3da051aeba.json: Language not supported
- .sqlx/query-53a76c5d7dbb79cb51cace5ffacc2cf689a650fb90bccfb80689ef3c5b73a2b0.json: Language not supported
- .sqlx/query-546d2bb7ff653c0ae1f6dcc5e68b12a670230de592557d27159acd2fc09400c6.json: Language not supported
- .sqlx/query-55e886a505d00b70674a19fd3228915ab4494cbd7058fdec868ab93c0fcfb4d8.json: Language not supported
- .sqlx/query-5bf9f8aacbe676339d0811d305abace6cc4a4d068392f7b58f2d165042ab509e.json: Language not supported
- .sqlx/query-5d36c126c67a5b70ac168bc46fcff3ee63ae5548ce78f244099f9d61ca694312.json: Language not supported
- .sqlx/query-5fea60d7574cfd238a7cbae4d93423869bd7b79dd5b246d80f0b6f39ce4659dc.json: Language not supported
- .sqlx/query-6cdfab7ffca4a98abcd7fb2325289ccf3035f08340bf80a345ff74570cd62043.json: Language not supported
- .sqlx/query-6e44fd63bcb2075e9515a7ce3d0be7a3759a98b5f1c637eb632aa440a1ffadb6.json: Language not supported
- .sqlx/query-722e059fca26aa3be81451ef5e266cc32d0e3ebc0611bd69013b6c3aa240b674.json: Language not supported
- .sqlx/query-7466afe658bdac4d522b96b33e769c130a1c5d065df70ce221490356c7eb806a.json: Language not supported
- .sqlx/query-7a6b4eb7eefd541ecb0529783ac01c36b2e69902623f289bd3cc6bf73d2b0ce8.json: Language not supported
- .sqlx/query-7b6c7e798237d0c08b7c1126d7044df13c46ef2eb373398a535090edf738cb5a.json: Language not supported
- .sqlx/query-7c087b528df89eb0bf41a4e46bcc48ab4946535a96baf0f49996d79387a3791c.json: Language not supported
- .sqlx/query-8038cec278228a04f83f4d67f8e2fd0382be589bf5d6dcde690b63f281160159.json: Language not supported
- .sqlx/query-8218dc7f0a2d15d19391bdcde1dfe27d2ee90aa4598b17d90e5db82244ad6ff1.json: Language not supported
- .sqlx/query-82eb411b1d8f6f3bed3db367ea147fbcd0626347744c7f8de6dce25d6e9a1fe7.json: Language not supported
- .sqlx/query-836ec7786ee20369b6b49aa89587480579468a5cb4ecdf7b315920b5e0bd894c.json: Language not supported
- .sqlx/query-83769682ee9bf8c76f1058a71b11d7d009683eef134e7be5b4ac285333822f58.json: Language not supported
- .sqlx/query-83cd9d573480c8a83e9e58f375653b4d76ec4c4dea338877ef5ba72fa49c28ad.json: Language not supported
- .sqlx/query-8aafae4565e572dc36aef3bb3d7b82a392e59683b9dfa1c457974e8fa8b7d00f.json: Language not supported
- .sqlx/query-8b3df91d5aec320fa8ffa47fc4d7fe61abe05cd5f4635d135d92dd605d065f56.json: Language not supported
- .sqlx/query-8bc673f6b9422bdc0e1f7b3aae61b851fb9d7b74a3ec519c9149f4948880d1be.json: Language not supported
- .sqlx/query-8cfb2d3a45ff6c5d1d51a98f6a37ba89da5a49c211c8627c314b8a32c92a62e1.json: Language not supported
- .sqlx/query-8db13c16e29b4aecd87646859296790f3e5971d7a2bff2d32f2d92590ec3393d.json: Language not supported
- .sqlx/query-8ec4c1e77a941efe4c1c36e26c5e1dfcb0e7769f0333d2acf7d6e0fb97ca12dc.json: Language not supported
- .sqlx/query-91966b9578edeb2303bbba93cfc756595265b21dd6f7a06a2f7a846d162b340c.json: Language not supported
- .sqlx/query-954605527a3ca7b9d6cbf1fbc03dc00c95626c94f0f02cbc69336836f95ec45e.json: Language not supported
- .sqlx/query-970e2fc198c379a19849c4621adeca951c761f6b9abd6c70158000e0c03ca7c7.json: Language not supported
- .sqlx/query-9d821bd27d5202d2c3d49a2f148ff7f21bafde8c7c1306cc7efc976a9eae0071.json: Language not supported
- .sqlx/query-9dc75c72351c3f0a7f2f13d1a638ff21ea671df07397a4f84fff3c2cb9bdec91.json: Language not supported
- .sqlx/query-9e4f216c828c7d53547c33da062153f90eefabe5a252f86d5e8d1964785025c0.json: Language not supported
- .sqlx/query-a24f6ae41366cfc2480a7d7832b1f823cc91662394ec8025b7ef486b85374411.json: Language not supported
- .sqlx/query-aa21279e6479dd588317bbb4c522094f0cf8736710de08963fff1178f2b62974.json: Language not supported
- .sqlx/query-ab22f5f84d90a3c2717cea339f6444c6c2656615fb29b4c04031a090cf103bdd.json: Language not supported
- .sqlx/query-b8296183bd28695d3a7574e57db445dc1f4b2d659a3805f92f6f5f83b562266b.json: Language not supported
- .sqlx/query-b92417574329b82cae2347027db12f4794c1fc48b67d64c34c88fd9caf4508f5.json: Language not supported
- .sqlx/query-bc798b1837501109ff69f44c01d39c1cc03348eb4b4fe698ad06283ba7072b7f.json: Language not supported
- .sqlx/query-c28d645182680aaeaf265abcb687ea36f2a01b6b778fd61921e0046ad3f2efb2.json: Language not supported
- .sqlx/query-c59246b73cf3c5a0fd961d2709477ce724f60cdb03492eef912a9fe89aee2ac4.json: Language not supported
- .sqlx/query-c9a83f9d610a79bef78e533dde75f527ab75ef319ef0584851feb5b893a9fa46.json: Language not supported
- .sqlx/query-cd6ddae34b29c15924e0ec26ea55c23d56315ad817bea716d6a71c8b2bb18087.json: Language not supported
- .sqlx/query-cf85345c0c38d7ba1c347a9cf027a55dccaaeb0fe55d5eabb7319a90cbdfe951.json: Language not supported
- .sqlx/query-d6ef8d90061834e8352f036e7fd7853451c03b83261fa43e564e8ad98a41c943.json: Language not supported
- .sqlx/query-d81dbcf77d096403614b80165d66388884b133c79da6ed1a5809a3ca64f48f97.json: Language not supported
- .sqlx/query-db15f82b91377978db22c48cf2fb4d54ef603448c0c44272aec8f2ff04920b83.json: Language not supported
- .sqlx/query-dd36c2beb4867d36db9dc0fe47e6310aea0a7dd4c8fc5f7c2cff4dac327cf3f7.json: Language not supported
- .sqlx/query-e5956a76c15941c58fc9acb3886c9d8ed8688d70ac5fcceaf41e1671f75dbaa8.json: Language not supported
- .sqlx/query-e5a60eb49da1cd42fc6c1bac36f038846f0cb4440e4b377d495ffe0f0bfc11b6.json: Language not supported
- .sqlx/query-f0af06a2002ce933966cf6cfe8289ea77781df5a251a6731b42f8ddefb8a4c8b.json: Language not supported
- .sqlx/query-f130c22d14ee2a99b9220ac1a45226ba97993ede9988a4c57d58bd066500a119.json: Language not supported
- .sqlx/query-f8611a862ed1d3b982e8aa5ccab21e00c42a3fad8082cf15c2af88cd8388f41b.json: Language not supported
- .sqlx/query-f93b65a30034b0558781a3173986706ad8a6255bba2812d4e32da205773c6de9.json: Language not supported
- .sqlx/query-fa51ae7af271fc17c848694fbf1b37d46c5a2f4202e1b8dce1f66a65069beb0b.json: Language not supported
- .sqlx/query-fb07f53c015c852c4ef9e0ce52541f06835f8687122987d87fad751981b0c2b1.json: Language not supported
- .sqlx/query-fb7ce69e70b345d2cf0ca017523c1b90b67b053add3d4cffb8d579bfc8f08345.json: Language not supported
- .sqlx/query-fde61fd37b0e4c325e9dd4817a5ccc4ed8a4ffd2175fce842dd5d33545ba63f2.json: Language not supported
- .sqlx/query-ffb567ac44b9a0525bd41392c3a865d0612bc0d3f620d5cba76a6b44a8812417.json: Language not supported
- .sqlx/query-ffd49d0e0354d8d4010863204b1a1f5406b31542b6b0219d7daa1705bf7b2f37.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/connectors/user_service/utils.rs
Outdated
| @@ -0,0 +1,16 @@ | |||
| /// Helper function to determine if a plan tier can access a required plan | |||
| /// Basic idea: enterprise >= professional >= basic | |||
| pub(crate) fn is_plan_upgrade(user_plan: &str, required_plan: &str) -> bool { | |||
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function name is_plan_upgrade is misleading. Based on the implementation (line 15: user_level > required_level), this function checks if the user's plan is higher tier than the required plan, not if it's an upgrade. Consider renaming to is_plan_higher_tier or has_plan_access to accurately reflect that it checks whether the user's plan meets or exceeds the requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
| if let Ok(enabled) = std::env::var("STACKER_CASBIN_RELOAD_ENABLED") { | ||
| config.casbin_reload_enabled = matches!(enabled.as_str(), "1" | "true" | "TRUE"); | ||
| } |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The boolean parsing logic for environment variables is duplicated across multiple settings. Consider extracting this into a helper function like parse_bool_env(value: &str) -> bool that handles common boolean representations consistently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
|
|
||
| database: | ||
| host: 172.17.0.2 | ||
| host: stackerdb |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The database host has been changed from an IP address to a hostname. Ensure that DNS resolution or Docker networking is properly configured for the stackerdb hostname to be resolvable in the local development environment.
| host: stackerdb | |
| host: 127.0.0.1 |
| }); | ||
|
|
||
| self.client | ||
| .post(&path) |
Check failure
Code scanning / CodeQL
Cleartext transmission of sensitive information High
user_id
This 'post' operation transmits data which may contain unencrypted sensitive data from
user_id
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 days ago
In general terms, the right fix is to ensure that this Vault client never uses an unencrypted transport when sending sensitive data. In practice for this snippet, that means validating self.address at the point where we construct the request URL and rejecting any non-HTTPS scheme, so that we never perform .post() to an insecure HTTP endpoint. We do not need to change the structure of the payload or the use of user_id in the path; the critical improvement is to guarantee TLS in transit.
The single best way to fix this without changing existing functionality is:
- In
store_ssh_key, instead of calling.post(&path)with a path string that might be missing a scheme or might usehttp://, parsepathas areqwest::Url(or asurl::Urlif preferred) and inspect its scheme. - If the scheme is not exactly
"https", return an error explaining that a secure Vault URL is required. - Call
.post(url)with the validatedUrlobject instead of the raw string.
This preserves all existing behavior for valid HTTPS Vault addresses while preventing cleartext transmission of the SSH keypair. To implement this we can use reqwest::Url (re-export of url::Url) which is part of the same crate already in use (reqwest), so no new external dependencies are needed. All changes occur inside src/helpers/vault.rs, in the body of store_ssh_key, around lines 219–235 where path is computed and used.
-
Copy modified lines R220-R224 -
Copy modified lines R226-R231 -
Copy modified line R242
| @@ -217,7 +217,18 @@ | ||
| private_key: &str, | ||
| ) -> Result<String, String> { | ||
| let path = self.ssh_key_path(user_id, server_id); | ||
| let url = reqwest::Url::parse(&path).map_err(|e| { | ||
| let msg = format!("Invalid Vault URL '{}': {}", path, e); | ||
| tracing::error!("{}", msg); | ||
| msg | ||
| })?; | ||
|
|
||
| if url.scheme() != "https" { | ||
| let msg = format!("Insecure Vault URL scheme '{}', HTTPS is required", url.scheme()); | ||
| tracing::error!("{}", msg); | ||
| return Err(msg); | ||
| } | ||
|
|
||
| let payload = json!({ | ||
| "data": { | ||
| "public_key": public_key, | ||
| @@ -229,7 +239,7 @@ | ||
| }); | ||
|
|
||
| self.client | ||
| .post(&path) | ||
| .post(url) | ||
| .header("X-Vault-Token", &self.token) | ||
| .json(&payload) | ||
| .send() |
|
|
||
| let response = self | ||
| .client | ||
| .get(&path) |
Check failure
Code scanning / CodeQL
Cleartext transmission of sensitive information High
user_id
This 'get' operation transmits data which may contain unencrypted sensitive data from
user_id
|
|
||
| let response = self | ||
| .client | ||
| .get(&path) |
Check failure
Code scanning / CodeQL
Cleartext transmission of sensitive information High
user_id
This 'get' operation transmits data which may contain unencrypted sensitive data from
user_id
- Extract container states from recent health command results - Build ContainerSnapshot array from HealthCommandReport data - Fixes empty containers array that prevented UI from showing app status
- Make dedicated query for health commands to always get results - Filter only completed health commands for container state extraction - Fixes containers array being empty due to exclude_results optimization
- Use HashMap to keep only most recent health check per app - Prevents duplicate container entries when multiple health checks exist
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: vsilent <42473+vsilent@users.noreply.github.com>
Co-authored-by: vsilent <42473+vsilent@users.noreply.github.com>
…arsing logic Co-authored-by: vsilent <42473+vsilent@users.noreply.github.com>
Co-authored-by: vsilent <42473+vsilent@users.noreply.github.com>
Rename is_plan_upgrade to is_plan_higher_tier
Extract parse_bool_env helper to deduplicate boolean parsing logic
No description provided.