# Complete Istockhomes Live Audit Report

**Status:** COMPLETE (read-only)  
**Authorized:** Brad Camp — Walter Directive — Complete Istockhomes Live Audit  
**Date:** 2026-07-25  
**Workspace:** `/Users/bradcamp/Desktop/The Complete Istockhomes/live/`  
**Secure config:** `App/secure/live/`  
**Stopping rule honored:** No code changes, no deployment, no streaming work, no App2 edits, no migrations, no new shell.

---

## Executive verdict

Live is a **Phase 2A authenticated product shell**: App2 login bridge, verification gate, first-use purpose/approval, and UI placeholders are real. **Streaming, camera/mic, recording, session persistence, and a business-identity header / trust footer are not production-ready.**

| Layer | Verdict |
|-------|---------|
| Auth bridge to App2 | **WORKING** (code-complete; production VERIFY required) |
| Verification gate | **WORKING** (logic present; production state matrix VERIFY) |
| Purpose / approval | **PARTIAL** (JSON file store; auto-approve on; no moderator UI) |
| Header (business identity) | **REPLACE IN PLACE** (generic Istockhomes Live chrome) |
| Footer (Istockhomes trust) | **REPLACE IN PLACE** (decorative “Certified” text; no `footer.ping`) |
| Business context | **PARTIAL** (session + ownership check; gaps on some pages) |
| Streaming / broadcast | **NOT BUILT** |
| App2 → Go Live entry | **BROKEN / MISSING** (no App2 dashboard “Go Live” link found) |

**Do not declare Live working without Brad’s production proof.**

---

## Post-audit addendum (2026-07-25, Brad response)

### Correct mental model

Live is **not** a finished streaming product that needs polishing. It is:

```
App2 → Authentication → Verification → Purpose / Approval → Placeholder for future Live services
```

| Bucket | Items |
|--------|--------|
| **GOOD (foundation)** | App2 auth bridge · verification gate · purpose/approval |
| **NEEDS REPAIR (Phase 2A)** | Header · footer · Dashboard→Go Live journey · business context · authorization · `/live/admin/` decision |
| **NOT BUILT (Phase 2B)** | Camera · mic · recording · broadcast · comments · analytics · scheduling · replay |

Missing **App2 Dashboard → Go Live** is a higher user-facing priority than the decorative footer: without a natural entry, Live almost does not exist.

`/live/admin/` must be **remove · secure · or complete** — never remain an unauthenticated stub.

### Phase split

- **Phase 2A** — journey + chrome + trust footer + admin decision — **no streaming**  
- **Phase 2B** — actually build Live capabilities  

### Open question before authorizing Phase 2A / 2B

**ANSWERED.** Canonical mission: [`LIVE_V1_MISSION.md`](LIVE_V1_MISSION.md) — Business Communication under Trust Layer; eight V1 capabilities including Showcase and Negotiation Room.

---

## 1. Complete Live file map

### 1.1 PHP pages

| File | Purpose | Called by | Dependencies | Status | Class |
|------|---------|-----------|--------------|--------|-------|
| `index.php` | Public Live home / status summary | Direct `/live/` | bootstrap, layout, auth (optional) | Soft auth shell | **KEEP** (content REPAIR later for business chrome) |
| `dashboard.php` | Signed-in Live control center | Nav, redirects, post-login | auth, approvals, layout | Auth + gate + approval UI | **KEEP** / body REPAIR for placeholders |
| `go-live.php` | Purpose form + post-approval choice shell | Nav, dashboard CTAs | auth, approvals, layout | Purpose WORKING; stream NOT BUILT | **KEEP** |
| `schedule-live.php` | Schedule form shell (not persisted) | Nav, go-live | bootstrap, layout, approval check only | PLACEHOLDER | **REPAIR** (persist later; re-check verification) |
| `signin.php` | Live-hosted App2 `auth.login` | Header, require_login | http, auth, layout | WORKING bridge | **KEEP** / CSRF REPAIR later |
| `logout.php` | Shared session logout | Header | auth | WORKING | **KEEP** / consider POST later |
| `video.php` | Business video workflow shell | Nav, dashboard | layout only | PLACEHOLDER | **LEGACY/PLACEHOLDER** until video phase |
| `watch.php` | Public watch/embed placeholder | Shares, replays | layout optional | PLACEHOLDER | **LEGACY/PLACEHOLDER** |
| `admin/index.php` | Future moderator UI stub | Direct URL | layout | Public stub | **REPAIR** (auth gate) before any real admin |
| `api/index.php` | JSON health/status stub | `/live/api/` | config | Stub only | **KEEP** as stub / expand later |
| `replays/index.php` | Replay catalog placeholder | Direct, video | layout | PLACEHOLDER | **LEGACY/PLACEHOLDER** |
| `docs/index.php` | Markdown doc browser | Footer Docs | filesystem | Public docs | **REPAIR** (auth or deny in prod if sensitive) |
| `scripts/test-phase2a-auth.php` | CLI Phase 2A unit checks | CLI only | auth, approvals | Test harness | **KEEP** (ensure not web-served) |

### 1.2 Includes

| File | Purpose | Called by | Status | Class |
|------|---------|-----------|--------|-------|
| `includes/bootstrap.php` | Session path=/; load stack | All pages | WORKING | **KEEP** |
| `includes/config.php` | Merge secure live-config | bootstrap | WORKING | **KEEP** |
| `includes/helpers.php` | URLs, escaping, approval helpers | pages/includes | WORKING | **KEEP** |
| `includes/http.php` | cURL JSON to App2 API | auth, signin | WORKING | **KEEP** |
| `includes/auth.php` | App2 identity, business list/switch, verification gate, safe return | protected pages | WORKING core | **KEEP** / extend for branding data |
| `includes/approvals.php` | JSON purpose store under secure | go-live, dashboard | PARTIAL | **KEEP** until Migration 023 |
| `includes/layout.php` | Generic header/footer chrome | most pages | Wrong architecture vs restore rule | **REPLACE IN PLACE** (same include role; business header + trust footer contract) |

### 1.3 Assets

| File | Purpose | Status | Class |
|------|---------|--------|-------|
| `assets/live.css` | Shell styles; sticky header; responsive nav scroll; panels | PARTIAL (no real logo/fonts loaded) | **REPAIR** with chrome restore |
| `assets/live.js` | Share + clipboard only; **no** WebRTC | PLACEHOLDER for media | **KEEP** for now |

### 1.4 Secure Foundation (outside `/live/` — not uploaded as Live app)

| File | Purpose | Class |
|------|---------|-------|
| `App/secure/live/live-config.php` | Non-secret flags; `streaming_enabled=false`; auto_approve | **KEEP** |
| `App/secure/live/.htaccess` | Deny web | **KEEP** |
| `App/secure/live/approvals/*` | Per-franchise JSON approvals | **KEEP** (interim) |
| `App/secure/live/README.md` | Rules | **KEEP** |

**Secrets in `/live/`:** None found (OpenAI path is a string reference only). Password fields exist only for login POST to App2 — expected.

### 1.5 Documentation

All under `live/docs/` including this report, Phase 2A reports, restore architecture, schema proposal (not executed). **KEEP.**

### 1.6 Unused / duplicate / legacy

| Item | Note | Class |
|------|------|-------|
| Demo video id `bv_demo_0001` | Hardcoded across video/replays/dashboard | PLACEHOLDER — remove when real videos exist |
| Deprecated session demo approval helpers in `helpers.php` | Prefer `approvals.php` | **REMOVE LATER** after caller proof |
| Old name stub `ACTIVE_BUSINESS_IDENTITY_AND_TRUST_SHELL.md` | Pointer only | **KEEP** as stub |
| Competing Live chrome vs App2 header/footer | Drift — Phase 2 restore | **REPLACE IN PLACE** layout |

### 1.7 External services / DB

| Dependency | Use |
|------------|-----|
| App2 API (`auth.login`, `auth.me`, `auth.logout`, `franchise.listMine`, `franchise.status`) | Identity + verification |
| PHP session (shared cookie `path=/`) | Token continuity with App2 |
| Filesystem JSON approvals | First-use purpose |
| MySQL from Live | **None directly** |
| LiveKit / WebRTC / CDN | **None** |
| OpenAI | **Not loaded** (path reference only) |

### 1.8 App2 handoff (outside live/, observed for journey)

| Finding | Detail |
|---------|--------|
| Shared session | `App2/bootstrap.php` cookie `path=/`; safe `?return=` for `/live/…` |
| Verification return | Live CTA → `/App2/verification.php?return=/live/dashboard.php` |
| **Go Live from App2 dashboard** | **No link found** in `App2/dashboard.php` (or App2 PHP grep) to `/live/` |

**Journey gap:** “Dashboard → Select Business → Go Live” is **incomplete on App2**. User must manually open `/live/` (or bookmark). Phase 2 repair list should add a business-context Live entry on App2 dashboard — **not done in this audit.**

---

## 2. Current user journey (as implemented)

```
Manual /live/  (App2 “Go Live” link MISSING)
  → index.php (optional sign-in)
  → signin.php → App2 auth.login
       ├─ requires_2fa → /App2/login-2fa.php?return=/live/…
       └─ token → shared session → auth.me
  → dashboard.php
       ├─ gate ≠ ok → verification panel → App2 verification.php?return=/live/dashboard.php
       ├─ no approval → go-live.php purpose form
       │     └─ auto_approve_when_verified=true → approved
       └─ approved → buttons: Go Live Now / Schedule / Business Videos
            ├─ go-live.php?intent=now → WARNING only (no stream)
            ├─ schedule-live.php → draft echo only (not saved)
            └─ video.php / watch.php / replays → placeholders
  → logout.php → auth.logout + destroy session
```

Documented safe verification detour (intended):

`/live/dashboard.php` → `/App2/verification.php` → steps → `/live/dashboard.php`  
(`live_safe_return_path` / App2 `app2_safe_return_path` — no open redirects)

---

## 3. Header findings

| Check | Result |
|-------|--------|
| Loads active business (not generic Live) | **FAIL** — brand text “Istockhomes” + “Live” |
| Business logo / name / colours from canonical data | **FAIL** — CSS circle mark only; no franchise branding |
| Preserves business ID in chrome | **FAIL** in header (ID exists in dashboard body only) |
| Logo → business Dashboard context | **FAIL** — links to `/live/index.php` |
| Clear Dashboard return (App2 business context) | **FAIL** — footer “Return to App2” is generic `/App2/` |
| Current Business ▼ | **NOT BUILT** in header (dashboard has select form if multi-business) |
| Login / logout | **WORKING** in header |
| Desktop / tablet / phone | **PARTIAL** — sticky header + horizontal nav scroll; no real logo; fonts named but not loaded |
| Outdated / static / duplicated markup | Generic Live chrome; duplicates App2 header role incorrectly |
| Accessible / keyboard | Skip link + nav present; **PARTIAL** — no business menu yet |

**Classification:** `layout.php` header → **REPLACE IN PLACE** (restore business-identity component; do not invent a third shell).

---

## 4. Footer findings

| Check | Result |
|-------|--------|
| Proper Istockhomes logo | **FAIL** — text only |
| Active business name + canonical ID | **FAIL** |
| Authenticated user authorized for business | **FAIL** (not shown; logic exists elsewhere in auth) |
| User certification current | **FAIL** in footer |
| Business verification current | **FAIL** in footer |
| Live meaningful `footer.ping` | **FAIL** — never called from Live |
| Distinct failed / unverified / verified | **FAIL** — static “Certified by Istockhomes” |
| Static Certified when validation fails | **FAIL risk** — always shows Certified text |
| Copied page cannot fake certification | **FAIL** — decorative text forgeable |
| Footer links current | **PARTIAL** — App2 + docs |
| Mobile / desktop | **PARTIAL** — simple stack |

**Classification:** Live footer → **REPLACE IN PLACE** to App2 trust-footer contract (`App2/includes/footer.php` pattern + `footer.ping`).

Note: Live intentionally **clears** `footer_key` on login to avoid stale keys, but never loads a fresh key for ping — trust footer cannot work until that contract is restored.

---

## 5. Business-context findings

| Question | Answer |
|----------|--------|
| Who is signed in? | App2 Bearer in `$_SESSION['token']`; refreshed via `auth.me` |
| Which business? | `live_auth_current_business()`: session `live_business_id` / `franchise_id` if owned, else first from `franchise.listMine` |
| Authorized? | Switch only if franchise in `listMine`; status via `franchise.status` |
| Business verified? | `franchise.status` → `certified` |
| Survives refresh? | **YES** if session cookie intact |
| Survives Live nav? | **YES** for pages using auth helpers |
| Survives verification detour? | **INTENDED YES** via shared session + safe return — **PRODUCTION VERIFY** |
| Survives login? | Sets franchise from `auth.me` when present |
| Survives logout? | Cleared |
| Browser back / second tab? | Same session cookie — **LIKELY YES**; race on switch — **UNKNOWN — PRODUCTION TEST** |
| URL/hidden field trusted alone? | Switch POST requires ownership check — **GOOD**. `watch.php?v=` accepts any string — **no business ACL** (placeholder) |

**Gaps:** `schedule-live.php` checks approval only — **does not re-assert verification gate**. `video.php` / `watch.php` / `replays` — **no business context**.

---

## 6. Verification-gate findings

Implemented in `live_auth_verification_gate` + panel renderer:

| State | Code support | Production proof |
|-------|--------------|------------------|
| User unverified, business verified | `gate=user` | **VERIFY** |
| User verified, business unverified | `gate=business` | **VERIFY** |
| Both unverified | `gate=both` | **VERIFY** |
| Both verified | `gate=ok` | **VERIFY** |
| No selected business | `gate=no_business` | **VERIFY** |
| Invalid business ID | Rejected on switch if not owned | **VERIFY** |
| Business owned by another user | Not settable via switch | **VERIFY** |
| Session expired | `auth.me` fail clears token | **VERIFY** |
| Certification changed mid-session | Next `auth.me` refresh | **VERIFY** (static cache per-request only) |

CTA uses App2 verification with `return=/live/dashboard.php`. Component ticks (email/phone/face) shown when user incomplete.

**Classification:** Gate logic **KEEP**. Production matrix **REQUIRED** (Phase 1 overlap).

---

## 7. Streaming and functional findings (after the gate)

| Feature | Classification |
|---------|----------------|
| Purpose question | **WORKING** (file-backed) |
| First-use onboarding / auto-approve | **PARTIAL** (`auto_approve_when_verified=true`; no human moderator) |
| Live Dashboard | **PARTIAL** (identity real; lists placeholder) |
| Camera / microphone checks | **NOT BUILT** |
| Stream creation | **NOT BUILT** |
| Preview | **NOT BUILT** |
| Start/stop controls | **NOT BUILT** (`intent=now` warning only) |
| Recording | **NOT BUILT** |
| Audience destination | **NOT BUILT** |
| Titles / descriptions | **PLACEHOLDER** (schedule form not saved) |
| Business branding overlays | **NOT BUILT** |
| Comments / interaction | **NOT BUILT** |
| Saving / publishing recordings | **NOT BUILT** |
| Error recovery (stream) | **NOT BUILT** |
| Analytics | **NOT BUILT** |
| Return to selected business (App2) | **BROKEN / WEAK** (generic App2 link) |
| Logout / session expiry | **WORKING** / **PARTIAL** |
| Share / copy (JS) | **WORKING** (demo URLs) |
| Admin moderation | **PLACEHOLDER** + **security gap** (no auth) |
| Live API | **PLACEHOLDER** |

**Rule applied:** A button or page existing ≠ WORKING.

---

## 8. Security and privacy findings

| Area | Finding | Severity |
|------|---------|----------|
| Auth on protected pages | dashboard, go-live, schedule require login | OK for phase |
| Auth on admin | **Missing** | High when admin becomes real |
| Auth on video/watch/docs/api | Public by design (stubs) | Medium if docs sensitive |
| Business auth on writes | Purpose save uses gate business id after verify | OK |
| CSRF | No tokens on POST (signin, purpose, switch, schedule) | Medium |
| Logout CSRF | GET logout | Low–Medium |
| Output escaping | `live_h()` used widely | Generally OK |
| SQL | None in Live | N/A |
| File upload | None | N/A |
| Stream keys | None | N/A |
| Secrets in `/live/` | None found | OK |
| Session | httponly; secure when HTTPS; SameSite Lax; path=/ | OK for shared auth |
| Rate limiting | None in Live | Rely on App2/edge |
| Error leakage | Generic messages mostly | OK |
| PII logging | No obvious Live logger | OK |
| Camera/mic consent | N/A (not built) | — |
| Recording consent | N/A | — |
| Safe return URLs | Restricted to `/live/` and `/App2/` | OK |
| Direct URL to protected pages | Redirect to signin | OK |
| Docs browser | Basename-restricted; public | Review for prod |
| CLI test script | Must not be web-reachable | Confirm server config |

---

## 9. Mobile / responsive findings

- Sticky header; nav `overflow-x: auto` — usable on small screens for current shell.
- Choice grids collapse at ~640–700px.
- `prefers-reduced-motion` respected.
- **No** real logos tested; brand fonts not loaded (system fallback).
- Trust footer / business header acceptance **not met** on any viewport.
- **PRODUCTION TEST** required on phone/tablet after chrome restore.

---

## 10. Broken links and dead ends

| Item | Issue |
|------|-------|
| App2 dashboard → Go Live | **No entry link found** |
| Header logo → business dashboard | Goes to Live home, not App2 `?franchise=` |
| Footer “Certified” | Dead-end trust claim (not validated) |
| Go Live Now | Dead end: warning, no stream |
| Schedule submit | Echo only; not stored |
| Business Videos / watch / replays | Demo-only loops |
| Admin | Empty future page, unauthenticated |
| Streaming/Moderation/Payments pills on home | Visual `is-off` even if config “On” (cosmetic bug) |

---

## 11. Classification summary (components)

| Component | Class |
|-----------|-------|
| Auth bridge (`auth.php`, `signin`, `logout`, `http`) | **KEEP** |
| Verification gate | **KEEP** |
| Approvals JSON | **KEEP** (interim) |
| `layout.php` header | **REPLACE IN PLACE** |
| `layout.php` footer | **REPLACE IN PLACE** |
| `live.css` / `live.js` | **REPAIR** / **KEEP** |
| dashboard / go-live pages | **KEEP** (content REPAIR) |
| schedule / video / watch / replays | **PLACEHOLDER** → future phase |
| admin | **REPAIR** (auth) before use |
| streaming stack | **NOT BUILT** |
| App2 Go Live entry | **REPAIR** (add link) — App2 touch, separate auth |
| Migration 023 | **NOT EXECUTED** — leave |

---

## 12. Exact files proposed for Phase 2 repair (after Phase 1 gate)

**Begin only when:** Brad is Certified and can return to Live; Phase 1 verification success criteria met.

| Priority | File / area | Action |
|----------|-------------|--------|
| 1 | Audit report → implementation plan | Authorize tightly controlled repair |
| 2 | `live/includes/layout.php` (+ CSS) | REPLACE IN PLACE → business header + trust footer contract |
| 3 | Live adapters to App2 header/footer **or** shared includes | One canonical identity + trust component; adapters only |
| 4 | `live/includes/auth.php` | Extend to supply branding fields for header (logo URL, colours) from App2 APIs — no second store |
| 5 | Footer `footer.ping` | Load footer_key safely; never expose in HTML; show fail states |
| 6 | App2 dashboard Live entry | Add Go Live → `/live/dashboard.php` preserving franchise context (**App2 change — separate BUILD LOCK list**) |
| 7 | `schedule-live.php` | Re-assert verification gate |
| 8 | `admin/index.php` | Require auth (or deny) |

**Do not** in that first repair: streaming, LiveKit, migrations, new shell package, bulk App2 redesign.

---

## 13. Files that must remain untouched (first repair pass)

- Streaming / WebRTC / provider code (none to touch — do not add)
- `App/secure/OpenAI-One-Key.php`
- App2 verification journey core (unless entry-link only, separately authorized)
- Migration 023 / new DB tables
- Working App2 `includes/header.php` / `footer.php` callers that already comply (audit-before-edit)
- Infrastructure folders (`_backups` policy already frozen)

---

## 14. Production tests Brad must perform

1. Sign into App2 with KatherineAir selected; note whether any Go Live control exists (expect none).  
2. Open `/live/` and `/live/dashboard.php` while signed in — confirm shared session.  
3. Run verification gate matrix (user/business combinations above).  
4. Complete verification via App2 with `return=/live/dashboard.php` — land back on Live.  
5. Submit purpose; confirm approval JSON under secure approvals (ops) and UI status.  
6. Confirm “Go Live Now” only warns — no camera prompt.  
7. Multi-business switch on Live dashboard; refresh; second tab.  
8. Logout from Live; confirm App2 also logged out (shared session).  
9. Confirm `/live/admin/` is reachable without auth (document risk).  
10. Mobile Safari/Chrome: Live nav and forms usable.  
11. After future chrome repair: KatherineAir logo, trust footer, real `footer.ping` — use restore acceptance list.

---

## 15. Rollback plan (for later implementation)

1. Before edits: dated folder under workspace `_backups/YYYY-MM-DD-live-chrome/` with copies of every file to change.  
2. Record `Deployment-History/YYYY-MM-DD/` entry.  
3. Production: prefer Live folder rename / prior zip restore; do not upload `_backups/` to server.  
4. Revert `layout.php` (+ CSS) and any auth branding helpers first — pages keep working with generic chrome if needed.  
5. Do not delete approvals JSON as part of chrome rollback.

---

## 16. Alignment with Project State

| Phase | Relation to this audit |
|-------|------------------------|
| **Phase 1 (ACTIVE)** | Verification journey — gate already coded in Live; Brad production certification is the blocker |
| **Phase 2 (BLOCKED)** | Header/footer restore + Live onboarding polish — **this audit is the input**; no PHP until Phase 1 done |
| **Streaming** | Not authorized; confirmed **NOT BUILT** |

---

## Stopping confirmation

This pass **stops after the audit**.

Walter did **not**:

- replace the header or footer  
- refactor Live  
- begin streaming development  
- change App2  
- create a new shell system  
- introduce database migrations  
- declare Live working without production proof  

**Next step (requires separate Brad authorization):** tightly controlled Phase 2 repair beginning with working business header, active-business context, and functioning Istockhomes trust footer — after Phase 1 verification succeeds.
