# Test Plan — SocialOps Agent Hub

Manual test plan mapped to the PRD's core requirements. Run after install
(before go-live) and after any update.

## 0. Environment
- [ ] PHP ≥ 8.1 (`php -v` or a `<?php phpinfo();` probe), extensions loaded:
      pdo_mysql, curl, openssl, mbstring, fileinfo, gd
- [ ] `storage/` outside the web document root; `https://site/storage/` → 403/404
- [ ] Installer removed after setup
- [ ] HTTPS active (padlock), app forces same

## 1. Authentication & RBAC
- [ ] Login with valid super-admin credentials works; wrong password shows generic error
- [ ] 5 failed logins lock the email+IP for a few minutes (throttle message)
- [ ] Logout clears session; Back button does not show protected pages
- [ ] Create users for each role: PROJECT_ADMIN, REVIEWER, AGENT, READ_ONLY
- [ ] READ_ONLY sees no action buttons and gets denied on any POST URL
- [ ] AGENT cannot approve; REVIEWER can approve but cannot manage users/settings
- [ ] Session idle timeout logs the user out after the configured minutes
- [ ] Every POST without a CSRF token is rejected (try curl with a valid cookie)

## 2. Project isolation (multi-project)
- [ ] Create 2 projects; switch via project switcher
- [ ] Content, sources, assets, calendar, social connections of project A are
      invisible while working in project B (spot-check each list page)
- [ ] Directly opening `content_view.php?id=<A's id>` while in B → denied
- [ ] Archiving a project hides it from the switcher; data retained

## 3. Sources & collector (official-only rule)
- [ ] Adding a source with a typo'd domain is rejected; official domains pass
- [ ] Collector fetches only from allowlisted official domains
- [ ] Items are classified (regulation/product/trust/event/other) and shown on Sources page
- [ ] An item can be converted into a Content record (Content Agent) with the
      source link preserved as a reference

## 4. Content, variants & review
- [ ] Content Agent produces a draft with per-platform variants within limits
      (e.g. X ≤ 280) — over-limit variants are flagged, not silently sent
- [ ] Fact-check agent marks claims with source references; compliance agent
      flags prohibited claims for an insurance project ("guaranteed returns…")
- [ ] Uniqueness agent flags a near-duplicate of an earlier post
- [ ] Editing approved content invalidates its approval (badge flips to
      "Approval invalid — content changed")
- [ ] Comment on a variant → task created; resolving the task clears it

## 5. Approval workflow (the critical gate)
- [ ] Draft → In Review → Approved transitions only by permitted roles
- [ ] AGENT attempting approve via crafted POST → denied (server-side check)
- [ ] Approval records approver, time and content hash (audit log shows it)
- [ ] Rejected content returns to Draft with reviewer note
- [ ] After approval, edit content → approval invalid → scheduler will NOT run it
- [ ] Schedule without valid approval → refused with message

## 6. Scheduling & publishing
- [ ] Schedule a post 5 minutes ahead; wait for cron → status becomes QUEUED → PUBLISHED
- [ ] Audit/publish result shows platform response summary, no tokens
- [ ] Failure path: disconnect token before run → status FAILED, notification created
- [ ] Retry after reconnecting works
- [ ] Two jobs at same minute both publish (queue processes all due jobs)

## 7. Social connections
- [ ] Connect flow opens official OAuth screen; callback lands back in app
- [ ] Token stored encrypted in DB (inspect row: not plaintext)
- [ ] Invalid/expired token marks connection INVALID and shows action item
- [ ] Disconnect requires admin confirmation (PRD §8)
- [ ] Publishing to a disconnected account is refused server-side

## 8. Calendar & UTM
- [ ] Month grid shows scheduled + published posts on correct days
- [ ] Coverage gap view highlights empty weeks vs cadence target
- [ ] Every scheduled post carries UTM parameters per project settings
- [ ] Manual "Add to calendar" creates a slot without content

## 9. AI settings & chat
- [ ] Without API key: agents fall back to rule-based mode (check draft output)
- [ ] With API key: agent chat answers; ai_runs logged with latency, no key stored in plaintext
- [ ] Invalid key → friendly error, no crash, no key in logs

## 10. Security spot-checks
- [ ] `storage/config.php` and `storage/keys/app_key.bin` not reachable via URL
- [ ] `asset.php?token=wrong` → 403; valid token serves file
- [ ] Uploaded .php file renamed/blocked (try uploading one as an asset)
- [ ] XSS: post title `<script>alert(1)</script>` renders escaped everywhere
- [ ] SQLi: search fields with `' OR 1=1 --` behave as plain text
- [ ] Audit log records login, approve, publish, connect, disconnect events

## 11. Cron / worker
- [ ] `worker_cron.php` runs via cPanel cron without output/errors
- [ ] `worker.php?token=…` works; wrong token → 403
- [ ] Health notification appears if queue has repeated failures
