# Phase 1: Foundations, Registry & OAuth - Discussion Log

> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

**Date:** 2026-05-21
**Phase:** 1-Foundations, Registry & OAuth
**Areas discussed:** Verification gap execution, Render-layer prototype, site_pages data + audit shape, Cross-repo coordination

---

## Verification gap execution (FND-01..06)

| Option | Description | Selected |
|--------|-------------|----------|
| Sequential, code-grounded | One gap at a time, grep/Read first, humans only after exhausting code. Slower, lower coordination cost | |
| Parallel, owner-driven | Spin up parallel threads with cloud-infra owner / Arda team / prototype. Fastest with responsive owners | |
| All Claude-led, escalate only when stuck | Claude investigates each via codebase reads, produces best-guess + confidence. Escalate humans only on LOW confidence | ✓ |
| Render-layer prototype first, rest parallel | Close FND-04 first as highest-leverage decision, others parallel after | |

**User's choice:** All Claude-led, escalate only when stuck
**Notes:** Each gap produces a written closure artifact in a Verification Memo. Phase 1 verifier checks all 6 closed before Phase 2 unblocks.

---

## Render-layer prototype (FND-04)

| Option | Description | Selected |
|--------|-------------|----------|
| Commit to iframe now, skip prototype | Research default. Structural isolation, bigscreen10 ships unchanged. Costs: nav outside iframe, single-doc scroll lost | |
| Run 1-day prototype, then decide | Adapt bigscreen10 both ways; decision based on real artifact | |
| Commit to scoped-inject, skip prototype | Single document; CSS scoping at publish-time required; rewrites selectors, @media, @keyframes | |
| Hybrid: iframe-by-default, manifest opt-in inject | Ship iframe for /10years; defer inject to later phases | |

**User's choice:** Scoped-inject + research React/Node packages for relevant approaches
**Notes:** User wanted inject for scroll cohesion + nav integration AND wanted researcher to survey ecosystem for relevant packages (not just commit blind).

### Follow-up: CSS isolation mechanism for inject

| Option | Description | Selected |
|--------|-------------|----------|
| Shadow DOM (web component wrapper) | Browser-native runtime isolation; SPA globals don't pierce; explicit re-import of resets/fonts needed | ✓ |
| Publish-time attribute-prefix selector rewriting | CLI rewrites all selectors to `[data-bsweb="<slug>"] ...`; must handle @media/@keyframes/CSS vars | |
| PostCSS / CSS Modules at publish time | Class-name scoping; struggles with element/global selectors | |
| Defer to researcher | Lock "scoped-inject" only; let RESEARCH.md propose mechanism | |

**User's choice:** Shadow DOM (web component wrapper)
**Notes:** Researcher must survey React/Node Shadow-DOM-mount packages (`react-shadow` etc.), document font/reset re-import strategy, and write a 1-day prototype task into PLAN.md.

---

## site_pages data + audit shape

### Schema model

| Option | Description | Selected |
|--------|-------------|----------|
| Single pointer + audit log | `site_pages.currentSha` + append-only `site_pages_audit`. Rollback via SQL UPDATE + lookup in audit | ✓ |
| Separate revisions table | `site_pages` + `site_page_revisions` (FK back). Cleaner history queries; more tables | |
| Append-only events table only | Event-sourcing pure. Max auditability; higher query cost | |
| Defer to planner | Lock semantics, let planner pick schema from cloud monorepo conventions | |

**User's choice:** Single pointer + audit log (research recommendation)

### Actor distinction (human vs agent)

| Option | Description | Selected |
|--------|-------------|----------|
| OAuth client_id distinguishes | Two Arda OAuth clients (human + agent); server reads client_id. Server-trusted | |
| Required X-Actor-Type header | CLI sends header per command; trusts client. Weaker | |
| Single client + scope difference | `website:write` vs `website:write:agent`. Couples scope to actor — awkward | |
| Single client + CLI-included claim, server-verified later | Simplest now; hardening deferred | ✓ |

**User's choice:** Single client + CLI-included claim, server-verified later
**Notes:** Audit row stores `actor_claim` + `verified: false`. Per-client distinction deferred to v2 hardening.

---

## Cross-repo coordination

| Option | Description | Selected |
|--------|-------------|----------|
| Doc-only SHA refs in PLAN.md | PLAN.md lists cloud-repo paths + expected SHA. Simplest, risk of drift | |
| Sister-PR cross-references | Each task references a cloud-repo PR. Best paper trail | |
| Git submodule | Add cloud as submodule, pinned SHA. Cost: recursive clones, fights GSD model | |
| Mirror: cloud work + summary commits here | Work in cloud PRs; summary commits in this repo per milestone. Lightweight | |

**User's choice:** Agent decides using best judgment → **Mirror approach** picked
**Notes:** Real work lands in cloud monorepo PRs. PLAN.md tracks via path + SHA refs. Where PRs exist, cross-link PR number. Executor commits here with `[cloud@SHA]` annotations.

---

## Claude's Discretion

- Column types in `site_pages` / `site_pages_audit` (TIMESTAMPTZ, varchar lengths, JSONB)
- LocalStack + Postgres versions (match cloud monorepo dev defaults)
- OAuth scope claim shape (per Arda convention)
- `requireScopeAndPolicy` invocation pattern (follow cloud precedent)
- Reserved-paths storage mechanism (TS const / JSON / DB table) — planner picks
- Rate-limit numerical values + scope (planner picks within constraints)
- Verification Memo file location

## Deferred Ideas

- `SiteEditor` Arda role (use `Admin` for v1)
- Per-actor OAuth clients (cryptographic actor verification) — v2
- Signed actor assertion alternative — v2
- DB-backed reserved paths (vs code config) — if need emerges
- Image optimization at publish — v2
- Draft URLs on prod CDN — v2
- Subsuming Builder.io routing — v2
- Webhooks on publish — out of scope

---

# Re-Discuss (2026-05-22) — FND-02 + FND-03 Reopen vs Arda V1

**Trigger:** ARDA-V1-BLOCKER.md (2026-05-22) — four contradictions between Phase 1 FND-02/FND-03 closures and Arda V1 OAuth client registration UI.

**Pre-discussion code investigation** (cloud monorepo `C:\Users\decid\gsd-workspaces\cloud\cloud`):
- `auth/OAuthClientDatabase.ts:236-238` — public-client registration hard-blocked (`ClientType.Public` throws "public clients are not supported in v1").
- `auth/OAuthTokens.ts:59-76` — `authenticateClient` requires + bcrypt-verifies `client_secret` on every `/oauth/token` call (auth_code + refresh_token grants).
- `api/src/OAuthApi.ts:138` — `/.well-known` advertises `response_types_supported: ["code"]` only; no `response_modes_supported` → fragment NOT supported in V1.
- `auth/OAuthClientDatabase.ts:51` — `IpRegistrationMismatch` audit enum present but no enforcement path in oauth/api code (field appears to drive admin_api SG, not OAuth-time checks).

**Consequence:** Brandon's "two-hop CLI-PKCE relay" hypothesis (CLI does PKCE exchange itself, dev-website relays code) is not viable. Confidential-client + mandatory secret means server must broker code exchange.

**Areas discussed:** Auth architecture pivot (FND-02 v2), dev-website role + redirect URI shape, Plan 01-03 router mount + scope sequencing, Server IPs field strategy.

---

## Auth architecture pivot (FND-02 v2) → D-13

| Option | Description | Selected |
|--------|-------------|----------|
| (A) dev-website = OAuth backend, vends Arda tokens to CLI | dev-website holds client_secret, runs PKCE exchange, returns Arda access + refresh tokens to CLI loopback. CLI calls apps/api directly with Arda bearer. Refresh wraps Arda /oauth/token through dev-website. | ✓ |
| (A') dev-website backend, vends dev-website session JWT (not Arda token) | dev-website mints its own signed JWT mapping to Arda identity + scopes. apps/api validates dev-website JWT. Adds internal auth layer. | |
| (C) Drop OAuth for v1, ship signed admin JWT | Skip Arda entirely. dev-website admin UI generates long-lived signed JWT. Loses per-user OAuth audit trail. | |
| (B) Block on Arda V2 (public-client + optional IPs) | Stop Phase 1 Tasks 3–5 until cloud team ships Arda V2 with public-client support. Unblock timeline unknown. | |

**User choice:** (A) — dev-website as OAuth backend holding client_secret, returning Arda tokens to CLI.

---

## Token custody (sub-question of A) → D-13 (verifier custody), D-15

| Option | Description | Selected |
|--------|-------------|----------|
| dev-website holds verifier + refresh; CLI gets access_token + session_id only | Stateful server, most secure, requires session store. | |
| dev-website holds verifier; CLI gets access_token + refresh_token | Stateless dev-website. CLI refreshes via dev-website (still needs secret-wrap). Simpler server, refresh material in CLI keychain. | ✓ |
| CLI holds verifier; dev-website is pure exchange proxy | Splits cryptographic state across two hosts. Weakest. | |

**User choice:** dev-website holds verifier; CLI gets BOTH tokens. dev-website is stateless secret-proxy for refresh.

---

## Token transport to loopback → D-14

| Option | Description | Selected |
|--------|-------------|----------|
| Browser redirect to `http://127.0.0.1:<port>/cb#tokens` (fragment) | Inline JS does `window.location` to loopback fragment. Tokens never appear in any HTTP log. Port from OAuth `state` param. | ✓ |
| Browser redirect to `http://127.0.0.1:<port>/cb?one_time_code` (CLI exchanges) | dev-website mints one-time code, CLI exchanges via POST. No inline JS. Needs short-lived server state. | |
| CLI polls `/api/cli-auth/poll?session_id=...` | No loopback server. Works behind aggressive firewalls. Long-polling state + UX latency. | |

**User choice:** fragment redirect — stateless dev-website, tokens never logged.

---

## Verifier storage on dev-website → D-15

| Option | Description | Selected |
|--------|-------------|----------|
| In-memory `Map<state, {verifier, port, exp}>` with 5min TTL | Zero infra. Single-instance fine for v1. Lost on restart → clean error → retry. | ✓ |
| Signed cookie on browser holding verifier | Stateless, multi-instance safe. Cookie size + key mgmt overhead. | |
| Postgres `auth_flow_state` table | Durable, multi-instance, auditable. Schema migration + cleanup overhead — overkill. | |

**User choice:** in-memory map.

---

## Exact-match redirect URI path → D-16

| Option | Description | Selected |
|--------|-------------|----------|
| `https://dev-website.bigscreencloud.com/oauth/cli-callback` | Top-level /oauth/* namespace. Clean separation from /api/cli-auth/* JSON endpoints. | ✓ |
| `https://dev-website.bigscreencloud.com/api/cli-auth/callback` | Single /api/cli-auth/* prefix. Slight overload (HTML response under /api/*). | |
| Both registered (multi-value redirectUris) | Future-proof migration. More attack surface. | |

**User choice:** `/oauth/cli-callback`.

---

## Plan 01-03 router mount target → D-18

| Option | Description | Selected |
|--------|-------------|----------|
| Correct Plan 01-03 to apps/api (FND-03 Option D holds) | Edit frontmatter: admin_api/admin_api.ts → api/api.ts. Server IPs become incidental (apps/api has no SG). | ✓ |
| Split: apps/api for site/*, apps/admin_api for /oauth/cli-* (dev-website mirrors admin) | site/* on apps/api per FND-03. dev-website OAuth code lives in dev-website repo. | |
| Revert FND-03: mount on apps/admin_api after all | Re-open FND-03. dev-website becomes both OAuth backend AND admin_api reverse proxy. Heavier. | |

**User choice:** correct Plan 01-03 to apps/api.

---

## Scope deploy sequencing → D-17 + D-19

| Option | Description | Selected |
|--------|-------------|----------|
| Cherry-pick 2 scope commits → fresh branch off dev-gem → PR → Arda deploy → THEN Plan 03 Task 3 | ~half-day cloud-team coordination. Clean state. | ✓ (with rename modification) |
| PR full dev-web-publisher branch (all 7 commits) | Larger review surface — ships Plan 01-02 + 01-03 Task 2 modules to dev-gem before they are integrated. | |
| Register client with empty scopes, update post-deploy | Two-step process, risk of forgetting step 2. | |

**User choice:** option 1 PLUS scope rename `site:*` → `website:*` BEFORE the PR.

**Notes:** No external callers yet, no deployed code references the literal `"website:read"`/etc. strings outside the OAuthScope catalog. Rename touches cloud commits a913ef2b + 983974ac and all website-repo planning docs. Clean window.

---

## Server IPs field strategy → D-16 (Server IPs sub-field)

| Option | Description | Selected |
|--------|-------------|----------|
| Fill with dev-website resolved IP(s) | dev-website is the only server calling /oauth/token. Semantically accurate; future-proof if Arda V2 adds enforcement. | ✓ |
| Fill with placeholder (0.0.0.0) + flag for Arda team to make optional | Blocks on Arda-team responsiveness. May fail validation. | |
| dev-website IPs + developer laptop IPs | Belt-and-suspenders. Laptop IPs unstable (original blocker). | |

**User choice:** dev-website IPs only.

---

## Action items for downstream agents

**For researcher (gsd-phase-researcher re-run if planner needs):**
- **R-NEW-01:** Resolve where dev-website OAuth backend code lives (CRA repo / new service / apps/api alias). Recommended: mount on apps/api + CNAME dev-website to apps/api LB. Verify against cloud `docs/architecture.md` + DNS state.
- Confirm exact router file in `apps/api` for site/* + /oauth/cli-* + /api/cli-auth/* mounts.
- Confirm cloud env-var naming convention for `ARDA_BSWEB_CLI_CLIENT_SECRET` (or equivalent).

**For planner (gsd-planner re-run for Plan 01-03):**
- Correct 01-03-PLAN.md frontmatter per D-18.
- Add new tasks for dev-website OAuth backend (start/callback/refresh handlers, in-memory state map, fragment-forward HTML template, integration tests). Probably new wave between Wave 3 and Wave 4, OR fold into Plan 01-03.
- Sequence the scope rename (D-17) and cherry-pick PR (D-19) as pre-requisites to Plan 01-03 Task 3.
- VERIFICATION-MEMO.md §FND-02 and §FND-03 require update to reflect superseded decisions.

**Deferred ideas added:**
- Arda V2 with public-client support — would let CLI do pure PKCE-loopback, eliminating dev-website OAuth backend. Track for v2 / Arda team roadmap.
- Persistent verifier storage (cookie or DB) — would enable multi-instance dev-website. Defer until multi-instance becomes a need.
