forgedashboardarchitecture

Dashboard App Manifest


app:
  name: dashboard
  description: >
    Personal hub — forge project state, LifeOS, misc tasks, and
    app integrations. Runs as a protected /dashboard route on
    astro-blog-site, fed by forge-denv HTTP API via Cloudflare tunnel.
  stack: astro
  version: 0.1.0
  status: planned
  cross_project:
    - forge          # denv HTTP API server (ANNOT-357)
    - forge-denv     # local runtime server + tunnel
    - astro-blog-site # host (this file lives here)
    - lifeos         # Supabase connection for /dashboard/lifeos

# ─── Domains ─────────────────────────────────────────────────────────────────

domains:
  - FORGE      # forge project state, graph, packets, annotations
  - TASKS      # misc tasks, inbox, iOS shortcut integration
  - LIFEOS     # LifeOS habits, goals, check-ins (pre-mobile web UI)
  - AUTH       # owner-only gate, session management
  - SHELL      # shared layout, nav, sidebar, design tokens

# ─── Screens ─────────────────────────────────────────────────────────────────

screens:
  - name: DashboardShell
    domain: SHELL
    path: src/pages/dashboard.astro
    notes: >
      Owner-only SSR gate. Checks session → redirects if not owner.
      Renders sidebar nav + slot for section pages.

  - name: ForgeStatusScreen
    domain: FORGE
    path: src/pages/dashboard/forge.astro

  - name: ForgeProjectScreen
    domain: FORGE
    path: src/pages/dashboard/forge/[project].astro
    notes: Per-project deep view — graph, diff, packet queue, annotations.

  - name: TasksScreen
    domain: TASKS
    path: src/pages/dashboard/tasks.astro

  - name: InboxScreen
    domain: TASKS
    path: src/pages/dashboard/inbox.astro
    notes: Unprocessed items from iOS Shortcuts POST.

  - name: LifeOSScreen
    domain: LIFEOS
    path: src/pages/dashboard/lifeos.astro

# ─── Features ────────────────────────────────────────────────────────────────

features:
  - name: forge_live_status
    kill_switch: false
    notes: forge-denv must be running locally + tunnel active.

  - name: forge_diff_view
    kill_switch: false
    notes: Shows forge verify --diff plan per domain.

  - name: forge_packet_queue
    kill_switch: false

  - name: forge_annotation_feed
    kill_switch: false

  - name: tasks_inbox
    kill_switch: false
    notes: iOS Shortcut integration via POST /api/tasks.

  - name: lifeos_integration
    kill_switch: true
    notes: Deferred — requires LifeOS Supabase connection.

  - name: cloudflare_tunnel
    kill_switch: false
    notes: forge-denv exposed via Cloudflare Tunnel. Graceful offline state when Mac not running.

# ─── Nodes Planned ───────────────────────────────────────────────────────────

nodes_planned:

  # SHELL
  - name: DashboardLayout
    type: layout
    domain: SHELL
    notes: Wraps all dashboard pages. Owner gate logic lives here.

  - name: DashboardNav
    type: component
    domain: SHELL
    notes: Sidebar nav with section links and active state.

  - name: OfflineState
    type: component
    domain: SHELL
    notes: >
      Shown when forge-denv is unreachable. Graceful degradation —
      does not break the dashboard for the owner.

  # AUTH
  - name: AuthGuard
    type: component
    domain: AUTH
    notes: >
      SSR auth check — reads session cookie, redirects non-owners.
      Reuses existing astro-blog-site auth primitives.

  # FORGE
  - name: ForgeStatusPanel
    type: component
    domain: FORGE
    notes: >
      React island. Fetches GET /api/status from forge-denv.
      Shows: project, phase, blocker, next_action, packet queue.

  - name: ForgeDiffPanel
    type: component
    domain: FORGE
    notes: >
      React island. Fetches GET /api/diff/:domain.
      Shows: planned vs present nodes per domain, ✓/✗ per node.
      First ✗ per domain labelled "← next".

  - name: ForgePacketPanel
    type: component
    domain: FORGE
    notes: >
      React island. Fetches GET /api/packets.
      Shows: pending/expired/failed counts, packet list with age + review status.

  - name: ForgeAnnotationFeed
    type: component
    domain: FORGE
    notes: >
      React island. Fetches GET /api/annotations.
      Shows: annotation list filtered by horizon, kind, severity.

  - name: ForgeGraphView
    type: component
    domain: FORGE
    notes: >
      React island. Fetches GET /api/graph.
      Renders manifest graph visually (D3 or similar).
      Deferred — lower priority than status/diff/packets.

  - name: ForgeAPIClient
    type: component
    domain: FORGE
    notes: >
      Shared fetch utility for all forge panels.
      Reads PUBLIC_FORGE_API_URL env var.
      Handles offline state — returns null on fetch failure,
      panels render OfflineState component.

  # TASKS
  - name: TaskList
    type: component
    domain: TASKS
    notes: >
      React island. Fetches GET /api/tasks.
      Shows: task list grouped by tag (misc, content, dev, etc.).
      Add task inline via POST /api/tasks.

  - name: InboxList
    type: component
    domain: TASKS
    notes: >
      React island. Fetches GET /api/inbox.
      Shows: unprocessed items from iOS Shortcuts.
      Triage actions: tag + move to tasks, or dismiss.

  # LIFEOS
  - name: LifeOSPanel
    type: component
    domain: LIFEOS
    notes: >
      React island. Connects to LifeOS Supabase project.
      Shows: habits, goals, check-ins, streaks.
      Kill-switched until LifeOS Supabase connection is live.
      Acts as primary LifeOS interface before mobile app ships.

# ─── Connections Planned ─────────────────────────────────────────────────────

connections_planned:
  # Auth gate
  - from: DashboardLayout
    to: AuthGuard
    type: depends_on

  # Forge panels → API client
  - from: ForgeStatusPanel
    to: ForgeAPIClient
    type: depends_on
  - from: ForgeDiffPanel
    to: ForgeAPIClient
    type: depends_on
  - from: ForgePacketPanel
    to: ForgeAPIClient
    type: depends_on
  - from: ForgeAnnotationFeed
    to: ForgeAPIClient
    type: depends_on
  - from: ForgeGraphView
    to: ForgeAPIClient
    type: depends_on

  # API client → forge-denv (external, via tunnel)
  - from: ForgeAPIClient
    to: forge-denv-http-api
    type: depends_on
    notes: External service. Offline-tolerant.

  # Screens → components
  - from: ForgeStatusScreen
    to: ForgeStatusPanel
    type: routes_to
  - from: ForgeStatusScreen
    to: ForgeDiffPanel
    type: routes_to
  - from: ForgeStatusScreen
    to: ForgePacketPanel
    type: routes_to
  - from: ForgeProjectScreen
    to: ForgeAnnotationFeed
    type: routes_to
  - from: ForgeProjectScreen
    to: ForgeGraphView
    type: routes_to
  - from: TasksScreen
    to: TaskList
    type: routes_to
  - from: InboxScreen
    to: InboxList
    type: routes_to
  - from: LifeOSScreen
    to: LifeOSPanel
    type: routes_to

  # Offline degradation
  - from: ForgeAPIClient
    to: OfflineState
    type: emits
    notes: emits when forge-denv unreachable

# ─── External Services ────────────────────────────────────────────────────────

external_services:
  - name: forge-denv-http-api
    url_env: PUBLIC_FORGE_API_URL
    notes: >
      forge-denv local server exposed via Cloudflare Tunnel.
      Set in Vercel env vars. Not always-on — requires Mac + tunnel running.
    auth:
      outer: Cloudflare Zero Trust Access (owner email only)
      inner: X-Forge-Token header from .secrets/forge-denv/.env

  - name: lifeos-supabase
    notes: >
      LifeOS Supabase project. Connected only when lifeos_integration
      kill-switch is enabled.
    status: planned

# ─── Infrastructure ──────────────────────────────────────────────────────────

infrastructure:
  tunnel:
    tool: cloudflare-tunnel
    tunnel_name: forge-local
    local_port: 7890
    subdomain: forge.yourdomain.com   # replace with actual domain
    always_on: launchd                # plist starts cloudflared on Mac login
    setup_steps:
      - brew install cloudflare/cloudflare/cloudflared
      - cloudflared tunnel login
      - cloudflared tunnel create forge-local
      - cloudflared tunnel route dns forge-local forge.yourdomain.com
      - create ~/.cloudflared/config.yaml (ingress → localhost:7890)
      - Cloudflare Zero Trust → Access → add application on subdomain
      - cloudflared service install  (launchd, starts on login)

  ios_shortcuts:
    - name: Add Task
      action: POST forge-denv /api/tasks
      payload: "{title, tags}"
      notes: Replaces Obsidian for capturing misc tasks from phone.
    - name: Start Forge
      action: open https://forge.yourdomain.com/dashboard
      notes: Tunnel already running via launchd — just opens the URL.

# ─── Slot Order (generation sequence) ────────────────────────────────────────

slot_order:
  # Foundation first
  - AuthGuard                 # auth primitives must exist before any page
  - DashboardLayout           # shell wraps everything
  - DashboardNav              # nav inside shell
  - OfflineState              # needed by all API-dependent components
  - ForgeAPIClient            # shared fetch — all panels depend on it

  # Forge panels (highest priority — core use case)
  - ForgeStatusPanel
  - ForgeDiffPanel
  - ForgePacketPanel
  - ForgeAnnotationFeed

  # Screens (after their components exist)
  - ForgeStatusScreen
  - ForgeProjectScreen

  # Tasks
  - TaskList
  - InboxList
  - TasksScreen
  - InboxScreen

  # LifeOS (kill-switched, do last)
  - LifeOSPanel
  - LifeOSScreen

  # Deferred
  - ForgeGraphView            # lower priority, do after core panels work

# ─── Config Keys ─────────────────────────────────────────────────────────────

config_keys:
  # Vercel env vars (PUBLIC_ prefix = client-accessible in Astro)
  - key: PUBLIC_FORGE_API_URL
    example: https://forge.yourdomain.com/api
    notes: Set in Vercel project settings. Never hardcoded.

  # forge-denv secrets (local only)
  - key: FORGE_TOKEN
    path: ~/Projects/.secrets/forge-denv/.env
    notes: Inner auth token. Sent as X-Forge-Token header from Astro.

# ─── Annotations Cross-Ref ───────────────────────────────────────────────────

annotations:
  - ANNOT-354: forge-denv HTTP API surface (forge project)
  - ANNOT-355: CLAUDE.md + forge_orient routing enforcement (forge)
  - ANNOT-356: Execution graph feedback loop gap (forge)
  - ANNOT-357: forge-denv Cloudflare tunnel + Astro integration (forge)
  - ANNOT-358: LifeOS web interface + misc tasks hub (forge)

← All notes