Update paths in docs and sudoers after services/ extraction
All references to server/telegram_bot/, server/ws_gateway/, server/corporate_memory/, server/session_collector* updated to their new locations under services/.
This commit is contained in:
parent
c6a711aa27
commit
2d3f127e58
7 changed files with 26 additions and 26 deletions
|
|
@ -154,7 +154,7 @@ When reopening the project in Claude Code:
|
||||||
- `src/parquet_manager.py` - Parquet conversion engine
|
- `src/parquet_manager.py` - Parquet conversion engine
|
||||||
- `connectors/jira/file_lock.py` - Advisory file locking
|
- `connectors/jira/file_lock.py` - Advisory file locking
|
||||||
- `connectors/jira/incremental_transform.py` - Jira monthly Parquet transform
|
- `connectors/jira/incremental_transform.py` - Jira monthly Parquet transform
|
||||||
- `server/ws_gateway/` - WebSocket notification gateway
|
- `services/ws_gateway/` - WebSocket notification gateway
|
||||||
|
|
||||||
## Git Commits & Pull Requests
|
## Git Commits & Pull Requests
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ notify-runner (cron, every 5min)
|
||||||
```
|
```
|
||||||
|
|
||||||
Notifications are delivered in parallel to both Telegram and the desktop app.
|
Notifications are delivered in parallel to both Telegram and the desktop app.
|
||||||
The WebSocket gateway (`server/ws_gateway/`) runs as a separate systemd service alongside the existing Telegram bot.
|
The WebSocket gateway (`services/ws_gateway/`) runs as a separate systemd service alongside the existing Telegram bot.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ Client -> Server: {"type":"pong"}
|
||||||
|
|
||||||
## Server Components
|
## Server Components
|
||||||
|
|
||||||
### WebSocket Gateway (`server/ws_gateway/`)
|
### WebSocket Gateway (`services/ws_gateway/`)
|
||||||
|
|
||||||
- `gateway.py` - main asyncio+aiohttp server with two listeners:
|
- `gateway.py` - main asyncio+aiohttp server with two listeners:
|
||||||
- TCP WebSocket on `127.0.0.1:8765` (proxied by nginx)
|
- TCP WebSocket on `127.0.0.1:8765` (proxied by nginx)
|
||||||
|
|
@ -121,7 +121,7 @@ Unlinking removes the entry from `desktop_users.json` but does not invalidate th
|
||||||
|
|
||||||
### Notification Dispatch
|
### Notification Dispatch
|
||||||
|
|
||||||
Both `server/bin/notify-runner` and `server/telegram_bot/bot.py` dispatch notifications to the WebSocket gateway alongside Telegram delivery. The webapp API (`POST /api/desktop/scripts/run`) also dispatches via `server/telegram_bot/dispatch.py`. The dispatch is fire-and-forget - if the gateway is not running, it silently skips.
|
Both `server/bin/notify-runner` and `services/telegram_bot/bot.py` dispatch notifications to the WebSocket gateway alongside Telegram delivery. The webapp API (`POST /api/desktop/scripts/run`) also dispatches via `services/telegram_bot/dispatch.py`. The dispatch is fire-and-forget - if the gateway is not running, it silently skips.
|
||||||
|
|
||||||
Script execution (from webapp API and Telegram bot) uses the `notify-scripts` helper:
|
Script execution (from webapp API and Telegram bot) uses the `notify-scripts` helper:
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ def deduplicate_and_merge(new_items: list, username: str):
|
||||||
|
|
||||||
### 1. Server-side Collector
|
### 1. Server-side Collector
|
||||||
|
|
||||||
**`server/corporate_memory/collector.py`** - Main collection logic:
|
**`services/corporate_memory/collector.py`** - Main collection logic:
|
||||||
- `collect_all()` - iteruje přes /home/*/CLAUDE.local.md
|
- `collect_all()` - iteruje přes /home/*/CLAUDE.local.md
|
||||||
- `should_process_user(username)` - kontrola hash změn (šetří tokeny)
|
- `should_process_user(username)` - kontrola hash změn (šetří tokeny)
|
||||||
- `extract_knowledge(content)` - volá HAIKU API
|
- `extract_knowledge(content)` - volá HAIKU API
|
||||||
|
|
@ -202,7 +202,7 @@ def deduplicate_and_merge(new_items: list, username: str):
|
||||||
- `save_knowledge(data)` - atomic JSON write
|
- `save_knowledge(data)` - atomic JSON write
|
||||||
- `update_user_hash(username, hash)` - uloží hash pro příští run
|
- `update_user_hash(username, hash)` - uloží hash pro příští run
|
||||||
|
|
||||||
**`server/corporate_memory/prompts.py`** - HAIKU prompts:
|
**`services/corporate_memory/prompts.py`** - HAIKU prompts:
|
||||||
- Prompt pro extrakci znalostí
|
- Prompt pro extrakci znalostí
|
||||||
- Prompt pro AI filtering citlivých dat
|
- Prompt pro AI filtering citlivých dat
|
||||||
- Prompt pro merge podobných znalostí (optional)
|
- Prompt pro merge podobných znalostí (optional)
|
||||||
|
|
@ -301,9 +301,9 @@ rsync -avz data-analyst:~/.claude_rules/ .claude/rules/ 2>/dev/null || \
|
||||||
## Implementation Phases
|
## Implementation Phases
|
||||||
|
|
||||||
### Phase 1: Server Infrastructure
|
### Phase 1: Server Infrastructure
|
||||||
1. `server/corporate_memory/` Python modul
|
1. `services/corporate_memory/` Python modul
|
||||||
2. `server/bin/collect-knowledge` wrapper
|
2. `server/bin/collect-knowledge` wrapper
|
||||||
3. `server/corporate-memory.service` + `.timer`
|
3. `services/corporate_memory/systemd/corporate-memory.service` + `.timer`
|
||||||
4. Update `server/deploy.sh`
|
4. Update `server/deploy.sh`
|
||||||
5. Update sudoers
|
5. Update sudoers
|
||||||
|
|
||||||
|
|
@ -336,7 +336,7 @@ rsync -avz data-analyst:~/.claude_rules/ .claude/rules/ 2>/dev/null || \
|
||||||
- **JSON I/O**: `webapp/telegram_service.py` - atomic writes with tempfile
|
- **JSON I/O**: `webapp/telegram_service.py` - atomic writes with tempfile
|
||||||
- **Dashboard widget**: `webapp/templates/dashboard.html` - KPI card pattern
|
- **Dashboard widget**: `webapp/templates/dashboard.html` - KPI card pattern
|
||||||
- **Sub-page**: `webapp/templates/catalog.html` - route + template pattern
|
- **Sub-page**: `webapp/templates/catalog.html` - route + template pattern
|
||||||
- **Systemd service**: `server/notify-bot.service` - timer pattern
|
- **Systemd service**: `services/telegram_bot/systemd/notify-bot.service` - timer pattern
|
||||||
- **Deploy**: `server/deploy.sh` - directory setup, script installation
|
- **Deploy**: `server/deploy.sh` - directory setup, script installation
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,7 @@ Given that notifications go to both Telegram and the desktop app, and there is n
|
||||||
|
|
||||||
#### Recommendations
|
#### Recommendations
|
||||||
|
|
||||||
1. **Immediate**: Change socket permissions to `0660` or `0770` in the bot code (`server/telegram_bot/bot.py`) or systemd service file. The socket is currently set to `0666` by an `ExecStartPost` or in code -- update to restrict to `data-ops` group.
|
1. **Immediate**: Change socket permissions to `0660` or `0770` in the bot code (`services/telegram_bot/bot.py`) or systemd service file. The socket is currently set to `0666` by an `ExecStartPost` or in code -- update to restrict to `data-ops` group.
|
||||||
|
|
||||||
2. **Better**: Add `SO_PEERCRED` validation in the bot's HTTP handler to verify the caller's UID and ensure they can only send notifications for their own username.
|
2. **Better**: Add `SO_PEERCRED` validation in the bot's HTTP handler to verify the caller's UID and ensure they can only send notifications for their own username.
|
||||||
|
|
||||||
|
|
@ -413,7 +413,7 @@ The `username` parameter comes from webapp request data or Telegram bot callback
|
||||||
|
|
||||||
#### Code Analysis
|
#### Code Analysis
|
||||||
|
|
||||||
In `server/telegram_bot/runner.py` (line 30):
|
In `services/telegram_bot/runner.py` (line 30):
|
||||||
```python
|
```python
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["/usr/bin/sudo", "-u", username, NOTIFY_SCRIPTS_BIN, "run", script_name],
|
["/usr/bin/sudo", "-u", username, NOTIFY_SCRIPTS_BIN, "run", script_name],
|
||||||
|
|
@ -638,7 +638,7 @@ All analyst home directories are `750`, but deploy's home is `755` (world-readab
|
||||||
**Severity:** MEDIUM
|
**Severity:** MEDIUM
|
||||||
**Source:** Codex second opinion
|
**Source:** Codex second opinion
|
||||||
|
|
||||||
The WebSocket gateway (`server/ws_gateway/gateway.py`) validates JWT tokens but does not:
|
The WebSocket gateway (`services/ws_gateway/gateway.py`) validates JWT tokens but does not:
|
||||||
- Check the `Origin` header of WebSocket connections
|
- Check the `Origin` header of WebSocket connections
|
||||||
- Implement replay protection (a captured auth message could be replayed within token validity)
|
- Implement replay protection (a captured auth message could be replayed within token validity)
|
||||||
- Bind tokens to specific connections or IP addresses
|
- Bind tokens to specific connections or IP addresses
|
||||||
|
|
@ -746,8 +746,8 @@ The following findings were identified by the OpenAI Codex second opinion review
|
||||||
- `server/sudoers-deploy`, `server/sudoers-webapp` (privilege escalation)
|
- `server/sudoers-deploy`, `server/sudoers-webapp` (privilege escalation)
|
||||||
- `server/deploy.sh` (CI/CD pipeline)
|
- `server/deploy.sh` (CI/CD pipeline)
|
||||||
- `server/bin/notify-runner`, `server/bin/notify-scripts` (notification pipeline)
|
- `server/bin/notify-runner`, `server/bin/notify-scripts` (notification pipeline)
|
||||||
- `server/telegram_bot/` (bot service, dispatch, runner)
|
- `services/telegram_bot/` (bot service, dispatch, runner)
|
||||||
- `server/ws_gateway/` (WebSocket gateway, JWT auth)
|
- `services/ws_gateway/` (WebSocket gateway, JWT auth)
|
||||||
- `webapp/desktop_auth.py`, `webapp/user_service.py` (auth flows)
|
- `webapp/desktop_auth.py`, `webapp/user_service.py` (auth flows)
|
||||||
- `.github/workflows/deploy.yml` (CI/CD configuration)
|
- `.github/workflows/deploy.yml` (CI/CD configuration)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -911,7 +911,7 @@ Gunicorn runs with a restricted PATH (only `/opt/data-analyst/.venv/bin`). There
|
||||||
- `/usr/local/bin/add-analyst`
|
- `/usr/local/bin/add-analyst`
|
||||||
- `/usr/local/bin/notify-scripts`
|
- `/usr/local/bin/notify-scripts`
|
||||||
|
|
||||||
This is handled in `webapp/user_service.py` and `server/telegram_bot/runner.py`.
|
This is handled in `webapp/user_service.py` and `services/telegram_bot/runner.py`.
|
||||||
|
|
||||||
### Username Generation
|
### Username Generation
|
||||||
|
|
||||||
|
|
@ -1103,8 +1103,8 @@ sudo -u <username> /usr/local/bin/notify-scripts sync-status
|
||||||
The `sync-status` command reads the mtime of `~/server/` directory. This is updated by `sync_data.sh` via `touch ~/server/` at the end of each sync. Each user has their own `~/server/` directory (containing symlinks to shared `/data/`), so timestamps are per-user.
|
The `sync-status` command reads the mtime of `~/server/` directory. This is updated by `sync_data.sh` via `touch ~/server/` at the end of each sync. Each user has their own `~/server/` directory (containing symlinks to shared `/data/`), so timestamps are per-user.
|
||||||
|
|
||||||
**Callers:**
|
**Callers:**
|
||||||
- `server/telegram_bot/status.py` - `/status` command and script list API
|
- `services/telegram_bot/status.py` - `/status` command and script list API
|
||||||
- `server/telegram_bot/runner.py` - on-demand script execution (Telegram "Run" button, webapp API)
|
- `services/telegram_bot/runner.py` - on-demand script execution (Telegram "Run" button, webapp API)
|
||||||
- `webapp/account_service.py` - Account card "Last Sync" display
|
- `webapp/account_service.py` - Account card "Last Sync" display
|
||||||
|
|
||||||
**Sudoers rules:**
|
**Sudoers rules:**
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Technical documentation for the notification engine (Phase 3, Issue #41).
|
||||||
|
|
||||||
### 1. Telegram Bot Service
|
### 1. Telegram Bot Service
|
||||||
|
|
||||||
**Source:** `server/telegram_bot/`
|
**Source:** `services/telegram_bot/`
|
||||||
|
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
|
|
@ -53,7 +53,7 @@ Technical documentation for the notification engine (Phase 3, Issue #41).
|
||||||
- `POST /send_photo` - send photo with caption (`user`, `photo_path`, `caption`)
|
- `POST /send_photo` - send photo with caption (`user`, `photo_path`, `caption`)
|
||||||
- `GET /health` - health check
|
- `GET /health` - health check
|
||||||
|
|
||||||
**Systemd service:** `server/notify-bot.service`
|
**Systemd service:** `services/telegram_bot/systemd/notify-bot.service`
|
||||||
- User: `deploy`, Group: `data-ops`
|
- User: `deploy`, Group: `data-ops`
|
||||||
- EnvironmentFile: `/opt/data-analyst/.env` (contains `TELEGRAM_BOT_TOKEN`)
|
- EnvironmentFile: `/opt/data-analyst/.env` (contains `TELEGRAM_BOT_TOKEN`)
|
||||||
- Restarts automatically on failure
|
- Restarts automatically on failure
|
||||||
|
|
@ -170,7 +170,7 @@ Scripts output JSON to stdout:
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `server/bin/notify-scripts` | `/usr/local/bin/notify-scripts` |
|
| `server/bin/notify-scripts` | `/usr/local/bin/notify-scripts` |
|
||||||
| `server/bin/notify-runner` | `/usr/local/bin/notify-runner` |
|
| `server/bin/notify-runner` | `/usr/local/bin/notify-runner` |
|
||||||
| `server/notify-bot.service` | `/etc/systemd/system/notify-bot.service` |
|
| `services/telegram_bot/systemd/notify-bot.service` | `/etc/systemd/system/notify-bot.service` |
|
||||||
| `examples/notifications/*.py` | `/data/docs/examples/notifications/` |
|
| `examples/notifications/*.py` | `/data/docs/examples/notifications/` |
|
||||||
| `docs/notifications.md` | `/data/docs/notifications.md` |
|
| `docs/notifications.md` | `/data/docs/notifications.md` |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ deploy ALL=(ALL) NOPASSWD: /usr/bin/chown deploy\:data-ops /data/notifications
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/chmod 2770 /data/notifications
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/chmod 2770 /data/notifications
|
||||||
|
|
||||||
# Allow deploy user to manage notify-bot service
|
# Allow deploy user to manage notify-bot service
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/server/notify-bot.service /etc/systemd/system/notify-bot.service
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/services/telegram_bot/systemd/notify-bot.service /etc/systemd/system/notify-bot.service
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl daemon-reload
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl daemon-reload
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart notify-bot
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart notify-bot
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start notify-bot
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start notify-bot
|
||||||
|
|
@ -74,7 +74,7 @@ deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl is-active notify-bot
|
||||||
deploy ALL=(%dataread) NOPASSWD: /usr/local/bin/notify-scripts
|
deploy ALL=(%dataread) NOPASSWD: /usr/local/bin/notify-scripts
|
||||||
|
|
||||||
# Allow deploy user to manage ws-gateway service
|
# Allow deploy user to manage ws-gateway service
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/server/ws-gateway.service /etc/systemd/system/ws-gateway.service
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/services/ws_gateway/systemd/ws-gateway.service /etc/systemd/system/ws-gateway.service
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart ws-gateway
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart ws-gateway
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start ws-gateway
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start ws-gateway
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop ws-gateway
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop ws-gateway
|
||||||
|
|
@ -105,8 +105,8 @@ deploy ALL=(ALL) NOPASSWD: /usr/bin/chmod 2770 /data/auth
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /data/corporate-memory
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /data/corporate-memory
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/chown deploy\:data-ops /data/corporate-memory
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/chown deploy\:data-ops /data/corporate-memory
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/chmod 2770 /data/corporate-memory
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/chmod 2770 /data/corporate-memory
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/server/corporate-memory.service /etc/systemd/system/corporate-memory.service
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/services/corporate_memory/systemd/corporate-memory.service /etc/systemd/system/corporate-memory.service
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/server/corporate-memory.timer /etc/systemd/system/corporate-memory.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/services/corporate_memory/systemd/corporate-memory.timer /etc/systemd/system/corporate-memory.timer
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable corporate-memory.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable corporate-memory.timer
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start corporate-memory.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start corporate-memory.timer
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop corporate-memory.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop corporate-memory.timer
|
||||||
|
|
@ -124,8 +124,8 @@ deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl is-enabled jira-sla-poll.timer
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /data/user_sessions
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /data/user_sessions
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/chown root\:data-ops /data/user_sessions
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/chown root\:data-ops /data/user_sessions
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/chmod 2770 /data/user_sessions
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/chmod 2770 /data/user_sessions
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/server/session-collector.service /etc/systemd/system/session-collector.service
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/services/session_collector/systemd/session-collector.service /etc/systemd/system/session-collector.service
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/server/session-collector.timer /etc/systemd/system/session-collector.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/cp /opt/data-analyst/repo/services/session_collector/systemd/session-collector.timer /etc/systemd/system/session-collector.timer
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable session-collector.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl enable session-collector.timer
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start session-collector.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start session-collector.timer
|
||||||
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop session-collector.timer
|
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop session-collector.timer
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue