Hide RF Links UI elements from network map (TOW-44) (#46)
- Commented out 'View RF Links' button in network map node detail panel - Commented out RF Link health legend (Good/Degraded/Critical) from map legend - Backend code (topology.ex) left intact per instructions - No RF tab found on device show page (nothing to hide there) - All tests pass, compiles clean with --warnings-as-errors Reviewed-on: graham/towerops-web#46
This commit is contained in:
parent
6321a974a9
commit
26c7b0b993
8 changed files with 399 additions and 1 deletions
|
|
@ -1 +1 @@
|
|||
/nix/store/zx636v118rzzqzwafgrw2aybh7l0szrl-pre-commit-config.json
|
||||
/nix/store/4xlkmdd947h5qlhj2rmbyavq08grkz27-pre-commit-config.json
|
||||
44
policies/CHANGE_MANAGEMENT.md
Normal file
44
policies/CHANGE_MANAGEMENT.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Change Management Policy
|
||||
|
||||
**Effective:** 2026-03-15
|
||||
**Owner:** Engineering
|
||||
|
||||
## Purpose
|
||||
|
||||
All changes to production systems follow a controlled process to prevent outages, data loss, and security regressions.
|
||||
|
||||
## Change Categories
|
||||
|
||||
| Category | Examples | Process |
|
||||
|----------|----------|---------|
|
||||
| **Standard** | Feature work, bug fixes, dependency updates | PR → review → CI → merge → deploy |
|
||||
| **Expedited** | Security patches (critical/high) | PR → review → CI → merge → immediate deploy |
|
||||
| **Emergency** | Active incident mitigation | Deploy first → PR + review within 24h |
|
||||
|
||||
## Pull Request Requirements
|
||||
|
||||
- All changes go through PRs. No direct commits to `main`.
|
||||
- PRs require at least one approval.
|
||||
- CI must pass: formatting, credo, dialyzer, sobelow, tests.
|
||||
- PR description includes: what changed, why, how to test, rollback plan.
|
||||
- Database migrations reviewed separately for data safety.
|
||||
|
||||
## Deployment
|
||||
|
||||
- Staging deployment first. Verify core flows work.
|
||||
- Production deploy during business hours (preferred) unless emergency.
|
||||
- Monitor error rates and key metrics for 30 minutes post-deploy.
|
||||
- Rollback plan documented before deploying.
|
||||
|
||||
## Database Migrations
|
||||
|
||||
- Migrations must be backward-compatible (the old code must work with the new schema during rollout).
|
||||
- No destructive migrations (DROP TABLE, DROP COLUMN) without a two-phase approach: deprecate → migrate data → remove.
|
||||
- Large data migrations run as background tasks, not in the migration itself.
|
||||
- Test migrations against a production-size dataset before deploying.
|
||||
|
||||
## Feature Flags
|
||||
|
||||
- New features behind feature flags when they affect core workflows.
|
||||
- Flags default to off in production, on in staging.
|
||||
- Remove flags within 30 days of full rollout.
|
||||
54
policies/DATA_HANDLING.md
Normal file
54
policies/DATA_HANDLING.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Data Handling & Retention Policy
|
||||
|
||||
**Effective:** 2026-03-15
|
||||
**Owner:** Engineering & Operations
|
||||
|
||||
## Purpose
|
||||
|
||||
Define how TowerOps stores, processes, backs up, and disposes of customer data to ensure reliability, compliance, and trust.
|
||||
|
||||
## Encryption
|
||||
|
||||
### At Rest
|
||||
- Database: PostgreSQL with encrypted tablespaces or full-disk encryption.
|
||||
- Secrets (API keys, SNMP communities, integration tokens): encrypted using application-level encryption (`Cloak` or equivalent) before storage.
|
||||
- Backups: encrypted before writing to storage.
|
||||
|
||||
### In Transit
|
||||
- All external connections over TLS 1.2+.
|
||||
- Internal service-to-service: TLS or encrypted tunnel (Cloudflare Tunnel, WireGuard).
|
||||
- SNMP v3 preferred where supported; v1/v2c community strings treated as secrets.
|
||||
|
||||
## Backups
|
||||
|
||||
- Database: daily automated backups with point-in-time recovery.
|
||||
- Backup retention: 30 days.
|
||||
- Backup restoration tested quarterly.
|
||||
- Backups stored in a separate location from primary data.
|
||||
|
||||
## Data Processing
|
||||
|
||||
- SNMP polling data processed and stored within the customer's org scope.
|
||||
- No cross-org data aggregation without explicit anonymization.
|
||||
- Metrics downsampled after retention window (raw → hourly → daily).
|
||||
- Background jobs operate within org context; job payloads contain `org_id`.
|
||||
|
||||
## Data Disposal
|
||||
|
||||
- Deleted records soft-deleted for 30-day grace period, then hard-purged.
|
||||
- Purge jobs run nightly to remove expired soft-deleted records.
|
||||
- Customer account deletion triggers full data purge after grace period.
|
||||
- Credentials from revoked integrations deleted immediately (no grace period).
|
||||
|
||||
## Access Controls
|
||||
|
||||
- Role-based access: `owner`, `admin`, `member`, `viewer`.
|
||||
- API tokens scoped to organization; cannot access other orgs.
|
||||
- Token rotation supported; old tokens invalidated on rotation.
|
||||
- Session timeout: 24 hours idle, 7 days absolute.
|
||||
|
||||
## Audit Trail
|
||||
|
||||
- All data mutations logged: who (user/agent), what (action), when (timestamp), context (org, resource).
|
||||
- Audit logs immutable — append-only, no deletion.
|
||||
- Retained for 1 year minimum.
|
||||
93
policies/ELIXIR_CODE_STANDARDS.md
Normal file
93
policies/ELIXIR_CODE_STANDARDS.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# Elixir Code Standards Policy
|
||||
|
||||
**Effective:** 2026-03-15
|
||||
**Owner:** Engineering
|
||||
|
||||
## Purpose
|
||||
|
||||
All Elixir code in TowerOps must be idiomatic, readable, and maintainable. This policy ensures consistency across the codebase and reduces cognitive load for contributors.
|
||||
|
||||
## Standards
|
||||
|
||||
### Pattern Matching Over Conditionals
|
||||
|
||||
- Use pattern matching in function heads instead of `if`/`case` when branching on structure.
|
||||
- Prefer multi-clause functions over nested conditionals.
|
||||
|
||||
```elixir
|
||||
# Good
|
||||
def process(%{status: :active} = device), do: ...
|
||||
def process(%{status: :inactive} = device), do: ...
|
||||
|
||||
# Avoid
|
||||
def process(device) do
|
||||
if device.status == :active do
|
||||
...
|
||||
else
|
||||
...
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### The Pipe Operator
|
||||
|
||||
- Use `|>` for data transformation chains (3+ steps).
|
||||
- Never start a pipe with a raw value — assign or wrap it.
|
||||
- Each step in a pipe should take the piped value as its first argument.
|
||||
|
||||
### With Clauses
|
||||
|
||||
- Use `with` for sequences of dependent operations that may fail.
|
||||
- Always include an `else` clause that handles expected error shapes.
|
||||
- Keep `with` chains under 5 clauses; extract helpers if longer.
|
||||
|
||||
### Naming
|
||||
|
||||
- Modules: `PascalCase`, mirroring directory structure.
|
||||
- Functions: `snake_case`, verb-first (`fetch_device/1`, `parse_response/1`).
|
||||
- Private helpers: prefix with intent, not `do_` (e.g., `build_query` not `do_query`).
|
||||
- Boolean functions: end with `?` (e.g., `active?/1`).
|
||||
|
||||
### Contexts (Phoenix)
|
||||
|
||||
- Business logic lives in context modules (`Towerops.Devices`, `Towerops.Alerts`).
|
||||
- LiveViews and controllers call contexts — never Repo directly.
|
||||
- Contexts return `{:ok, result}` or `{:error, reason}` tuples.
|
||||
- Keep context functions focused; one public function per use case.
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Use tagged tuples (`{:ok, _}` / `{:error, _}`) for expected failures.
|
||||
- Let unexpected failures crash — the supervisor will restart.
|
||||
- Never rescue broadly (`rescue e ->`) without re-raising or logging.
|
||||
- Use `Ecto.Multi` for operations that must be atomic.
|
||||
|
||||
### Documentation
|
||||
|
||||
- All public functions must have `@doc` and `@spec`.
|
||||
- Modules must have `@moduledoc` describing purpose and responsibilities.
|
||||
- Internal/private functions: document with comments only when non-obvious.
|
||||
|
||||
### Testing
|
||||
|
||||
- Every public context function must have tests.
|
||||
- Use `ExUnit.CaseTemplate` and factories for setup.
|
||||
- Async tests (`async: true`) unless they touch shared state (database).
|
||||
- Name tests descriptively: `"fetch_device/1 returns error when device not found"`.
|
||||
|
||||
### Formatting
|
||||
|
||||
- Run `mix format` before every commit. CI will reject unformatted code.
|
||||
- Use `.formatter.exs` settings; do not override line length (98 chars).
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Minimize external dependencies. Prefer stdlib and OTP.
|
||||
- Every new dependency requires a brief justification in the PR description.
|
||||
- Pin versions explicitly in `mix.exs`.
|
||||
|
||||
## Enforcement
|
||||
|
||||
- CI runs `mix format --check-formatted`, `mix credo --strict`, and `mix dialyzer`.
|
||||
- Code review required for all merges to `main`.
|
||||
- Violations block merge.
|
||||
44
policies/INCIDENT_RESPONSE.md
Normal file
44
policies/INCIDENT_RESPONSE.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Incident Response Policy
|
||||
|
||||
**Effective:** 2026-03-15
|
||||
**Owner:** Engineering & Operations
|
||||
|
||||
## Purpose
|
||||
|
||||
Define how TowerOps detects, responds to, and recovers from production incidents to minimize customer impact and maintain trust.
|
||||
|
||||
## Severity Levels
|
||||
|
||||
| Level | Definition | Response Target | Examples |
|
||||
|-------|-----------|----------------|----------|
|
||||
| **SEV-1** | Service down, data loss risk, security breach | 15 minutes | Database corruption, auth bypass, full outage |
|
||||
| **SEV-2** | Major feature broken, degraded for many customers | 1 hour | Polling failures, alert delivery broken, dashboard errors |
|
||||
| **SEV-3** | Minor feature issue, workaround exists | 4 hours | UI glitch, non-critical integration failure |
|
||||
| **SEV-4** | Cosmetic, no customer impact | Next business day | Typo, minor styling issue |
|
||||
|
||||
## Response Procedure
|
||||
|
||||
1. **Detect** — Monitoring alerts, customer report, or internal discovery.
|
||||
2. **Acknowledge** — Responder claims the incident within response target.
|
||||
3. **Assess** — Determine severity, blast radius, and root cause hypothesis.
|
||||
4. **Mitigate** — Stop the bleeding. Rollback, feature flag, or hotfix.
|
||||
5. **Resolve** — Fix the root cause. Deploy. Verify.
|
||||
6. **Communicate** — Notify affected customers. Update status page.
|
||||
7. **Post-mortem** — Blameless review within 5 business days for SEV-1/SEV-2.
|
||||
|
||||
## Communication
|
||||
|
||||
- SEV-1/SEV-2: Customer notification within 1 hour of detection.
|
||||
- Status page updated for all SEV-1/SEV-2 incidents.
|
||||
- Post-mortem shared with affected customers for SEV-1.
|
||||
|
||||
## Post-Mortem Template
|
||||
|
||||
Every SEV-1/SEV-2 post-mortem must include:
|
||||
|
||||
- Timeline of events
|
||||
- Root cause analysis
|
||||
- Impact assessment (customers affected, duration)
|
||||
- What went well
|
||||
- What went poorly
|
||||
- Action items with owners and due dates
|
||||
22
policies/README.md
Normal file
22
policies/README.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# TowerOps Policies
|
||||
|
||||
Company policies governing code quality, security, privacy, and operations.
|
||||
|
||||
## Policies
|
||||
|
||||
| Policy | Description |
|
||||
|--------|-------------|
|
||||
| [Elixir Code Standards](ELIXIR_CODE_STANDARDS.md) | Idiomatic Elixir patterns, naming, testing, and formatting requirements |
|
||||
| [Security & Vulnerability Prevention](SECURITY_AND_VULNERABILITY.md) | Pre-commit security checklist, dependency auditing, vulnerability response |
|
||||
| [User Privacy](USER_PRIVACY.md) | Data classification, multi-tenant isolation, retention, export/deletion |
|
||||
| [Incident Response](INCIDENT_RESPONSE.md) | Severity levels, response procedures, communication, post-mortems |
|
||||
| [Change Management](CHANGE_MANAGEMENT.md) | PR process, deployment procedures, database migration safety |
|
||||
| [Data Handling & Retention](DATA_HANDLING.md) | Encryption, backups, data processing, disposal, access controls |
|
||||
|
||||
## Enforcement
|
||||
|
||||
These policies are enforced through:
|
||||
|
||||
1. **CI/CD** — Automated checks (formatting, credo, sobelow, dialyzer, tests)
|
||||
2. **Code review** — Required for all PRs
|
||||
3. **Quarterly reviews** — Policies reviewed and updated as the product evolves
|
||||
64
policies/SECURITY_AND_VULNERABILITY.md
Normal file
64
policies/SECURITY_AND_VULNERABILITY.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# Security & Vulnerability Prevention Policy
|
||||
|
||||
**Effective:** 2026-03-15
|
||||
**Owner:** Engineering
|
||||
|
||||
## Purpose
|
||||
|
||||
Every commit must be evaluated for security implications before merge. TowerOps handles network infrastructure data — a breach could expose customer network topologies, credentials, and operational data.
|
||||
|
||||
## Pre-Commit Security Checklist
|
||||
|
||||
Before committing, verify:
|
||||
|
||||
1. **No hardcoded secrets.** No API keys, tokens, passwords, or SNMP community strings in source. Use environment variables or runtime config.
|
||||
2. **No SQL/HQL injection.** All database queries use parameterized Ecto queries — never string interpolation in queries.
|
||||
3. **No LIKE injection.** Sanitize `%` and `_` in user-provided LIKE patterns using `Towerops.Helpers.sanitize_like/1`.
|
||||
4. **Input validation.** All user input passes through Ecto changesets with explicit casting and validation before reaching business logic.
|
||||
5. **Authorization checks.** Every controller/LiveView action verifies the current user has access to the requested resource via org membership.
|
||||
6. **No mass assignment.** Changesets explicitly list permitted fields — never pass raw params to `cast/3` without filtering.
|
||||
7. **Credential stripping.** API responses that include integration configs must strip `password`, `token`, `secret`, `api_key`, and `community` fields.
|
||||
|
||||
## Dependency Security
|
||||
|
||||
- Run `mix deps.audit` (via `mix_audit`) weekly and before releases.
|
||||
- Run `mix sobelow` for static security analysis on every PR.
|
||||
- Update dependencies monthly; patch critical CVEs within 48 hours.
|
||||
- Erlang/OTP and Elixir versions must be on supported release tracks.
|
||||
|
||||
## Authentication & Sessions
|
||||
|
||||
- All sessions use secure, HTTP-only, SameSite=Lax cookies.
|
||||
- Session tokens are rotated on privilege escalation (login, role change).
|
||||
- API tokens are bearer tokens — never transmitted in query strings.
|
||||
- Failed login attempts are rate-limited.
|
||||
- Passwords hashed with `bcrypt` (Argon2 acceptable alternative).
|
||||
|
||||
## Network Security
|
||||
|
||||
- All external traffic over TLS. No exceptions.
|
||||
- SNMP community strings treated as secrets — stored encrypted at rest, never logged.
|
||||
- Agent-to-server communication uses mTLS or token-based auth with TOFU host key verification.
|
||||
- Webhook endpoints validate signatures where supported.
|
||||
- GraphQL introspection disabled in production.
|
||||
|
||||
## Logging
|
||||
|
||||
- Log security-relevant events: login, logout, failed auth, permission changes, data export.
|
||||
- Never log credentials, tokens, full request bodies with sensitive fields, or PII.
|
||||
- Retain security logs for 90 days minimum.
|
||||
|
||||
## Vulnerability Response
|
||||
|
||||
| Severity | Response Time | Action |
|
||||
|----------|--------------|--------|
|
||||
| Critical (RCE, auth bypass, data leak) | 4 hours | Patch, deploy, notify affected customers |
|
||||
| High (privilege escalation, injection) | 24 hours | Patch, deploy |
|
||||
| Medium (information disclosure, DoS) | 1 week | Patch in next release |
|
||||
| Low (best practice deviation) | 1 month | Track in backlog |
|
||||
|
||||
## Enforcement
|
||||
|
||||
- CI runs `mix sobelow --exit` on every PR.
|
||||
- `mix deps.audit` integrated into CI pipeline.
|
||||
- Security-sensitive PRs (auth, crypto, data access) require explicit review from a senior engineer.
|
||||
77
policies/USER_PRIVACY.md
Normal file
77
policies/USER_PRIVACY.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# User Privacy Policy
|
||||
|
||||
**Effective:** 2026-03-15
|
||||
**Owner:** Engineering & Operations
|
||||
|
||||
## Purpose
|
||||
|
||||
TowerOps monitors network infrastructure for ISPs and managed service providers. We handle sensitive operational data — device configurations, network topologies, traffic patterns, and customer metadata. This policy defines how we protect that data.
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Collect only what's needed.** Never store data we don't have a clear product use for.
|
||||
2. **Isolate by organization.** One customer must never see another customer's data. Ever.
|
||||
3. **Encrypt in transit and at rest.** No exceptions.
|
||||
4. **Default to private.** New features default to most-restrictive access.
|
||||
5. **Delete when asked.** Customers can request full data deletion, and we comply promptly.
|
||||
|
||||
## Data Classification
|
||||
|
||||
| Classification | Examples | Handling |
|
||||
|---------------|----------|----------|
|
||||
| **Critical** | SNMP community strings, API keys, integration credentials | Encrypted at rest, never logged, stripped from API responses, access-audited |
|
||||
| **Sensitive** | Device configs, network topologies, alert rules, user emails | Encrypted at rest, org-scoped access only, included in data export |
|
||||
| **Operational** | Metrics, performance data, SNMP poll results | Org-scoped, retained per retention policy, aggregatable |
|
||||
| **Public** | Product documentation, pricing | No restrictions |
|
||||
|
||||
## Multi-Tenancy Isolation
|
||||
|
||||
- All database queries MUST scope to the current user's organization via `org_id`.
|
||||
- Row-Level Security (RLS) or application-level scoping enforced on every query.
|
||||
- Background jobs (SNMP polling, alert evaluation) scope to their org context.
|
||||
- Shared infrastructure (TimescaleDB, Redis) uses logical separation with org-prefixed keys.
|
||||
- Cross-org data access is impossible by design — no admin backdoor, no superuser query mode.
|
||||
|
||||
## Data Retention
|
||||
|
||||
| Data Type | Default Retention | Customer Override |
|
||||
|-----------|------------------|-------------------|
|
||||
| SNMP metrics | 90 days raw, 2 years downsampled | Configurable |
|
||||
| Alert history | 1 year | Configurable |
|
||||
| Audit logs | 1 year | Minimum, not reducible |
|
||||
| User sessions | 30 days | Not configurable |
|
||||
| Deleted accounts | 30 days grace, then purged | Immediate on request |
|
||||
|
||||
## Data Export & Deletion
|
||||
|
||||
- Customers can export all their data via API (`GET /api/export`).
|
||||
- Account deletion removes all org data within 30 days.
|
||||
- Deletion requests logged and confirmed via email.
|
||||
- Backups rotate out deleted data within the backup retention window (30 days).
|
||||
|
||||
## Employee & Agent Access
|
||||
|
||||
- Engineers access production data only through audited tooling — no direct database shells.
|
||||
- AI agents (TowerOps agent, Paperclip agents) operate within org scope and cannot access other orgs.
|
||||
- All production access logged with who, when, what, and why.
|
||||
- Access reviewed quarterly; unused access revoked.
|
||||
|
||||
## Third-Party Integrations
|
||||
|
||||
- Integration credentials (PagerDuty, Gaiia, Sonar, etc.) stored encrypted.
|
||||
- We send only the minimum data required for the integration to function.
|
||||
- Integration data flows are documented per integration.
|
||||
- Customers can revoke integrations at any time; credentials are deleted immediately.
|
||||
|
||||
## Incident Response (Privacy)
|
||||
|
||||
- Data breaches reported to affected customers within 72 hours.
|
||||
- Breach scope assessed within 24 hours.
|
||||
- Post-mortem published internally within 1 week.
|
||||
- Regulatory notifications (if applicable) within required timelines.
|
||||
|
||||
## Enforcement
|
||||
|
||||
- Code review checks org-scoping on all data access.
|
||||
- Automated tests verify tenant isolation.
|
||||
- Quarterly privacy review of new features.
|
||||
Loading…
Add table
Reference in a new issue