Skip to content

docs: add R13 ops-cockpit spec and ADR-0001 (deck as panel-host) - #6

Merged
JustAGhosT merged 2 commits into
devfrom
docs/deck-ops-cockpit-spec-and-adr
Aug 10, 2026
Merged

docs: add R13 ops-cockpit spec and ADR-0001 (deck as panel-host)#6
JustAGhosT merged 2 commits into
devfrom
docs/deck-ops-cockpit-spec-and-adr

Conversation

@JustAGhosT

@JustAGhosT JustAGhosT commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Lands the detailed spec and ADR that baton task 0e6c0c19"Deck R13 focus: cost/ops cockpit, Mystira ops tooling, and story-gen batch-run ops" — has been blocked on since 2026-07-21 (NEXT: detailed spec + ADR required before build).

Both documents were authored 2026-07-11 and, until this PR, existed only as untracked files in a local working tree. No branch, no remote, no copy anywhere. A git clean -fd would have destroyed them.

What lands

File Status Establishes
docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md Proposed docs/adr/NNNN-*.md as deck's ADR home
docs/specs/deck-ops-cockpit.md Draft docs/specs/ as the home for deck design specs

ADR-0001 settles whether deck should reintroduce Mystira-specific surfaces into a shell that was deliberately made generic during the devhub→deck extraction. Decision: deck is a generic panel-host; Mystira ops tooling is hosted as bounded, individually-omissible panel modules on top of it — not folded into the shell, and not built as a separate app. Left at Proposed: nothing has been built against it yet.

The spec covers the three R13 facets — a Dashboard cost/ops section (sluice health + docket spend), the Cosmos Explorer + Migration Manager re-port, and a Service-Manager story-gen batch-run monitor — with per-facet readiness and the cross-repo dependency list.

Re-grounded against dev @ bc0d1c5

deck moved after these were written (PR #3 added the Camera panel and crates/deck-camera; PR #5 added CI). The design and both decisions are unchanged; the current-state evidence was corrected where it had gone stale:

  • §1.2's central claim was wrong. It recorded that the frontend could not typecheck, because AppContent.tsx / AppSidebar.tsx still imported the removed CosmosExplorer / MigrationManager and switched on undefined VIEWS members. PR feat(camera): add private local viewer #3 removed that wiring, and PR ci: add GitHub Actions workflow for Rust and UI #5's CI proves the build is green. The finding is kept in corrected form — the extraction is still unfinished, but the surviving evidence is behavioural: three Dashboard.tsx quick-actions calling onNavigate("cosmos") / onNavigate("migration") that fall through AppContent's default: to the Service Manager, orphaned StatisticsPanel.tsx / ExportPanel.tsx invoking Cosmos commands whose .NET handlers were stripped, and live Rust + .NET backends with no UI above them. A dated drift note in §1.2 records exactly what changed and why the conclusion still holds.
  • §1.1 now records crates/deck-camera, the six CI gates, and cites the Camera panel as the four-file recipe's most recent worked example.
  • §1.4 / §1.2 line references refreshed (main.rs:69, main.rs:42-43,86-90, constants.ts:2-8, Program.cs:126-127); get_cli_executable_path() is in helpers.rs:111-123, not cli.rs.

Claims re-verified as still accurate: the stripped cosmos.stats/cosmos.export .NET handlers, the present-and-registered cosmos.rs + MigrationService, the whole DevHub naming residue, and the dangling ../adr/0020-* breadcrumb in docs/guides/contracts-migration.md that motivates the docs/adr/ placement.

Notes for review

  • Docs-only — no code, no CI surface touched. Rust and UI jobs should pass untouched.
  • Committing endorses two new doc directories (docs/adr/, docs/specs/); deck previously had only docs/guides/. Rationale for both is in the spec header and ADR §Notes on placement.
  • The ADR stays Proposed rather than Accepted — flip it when Facet 2 work actually starts.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Added an architecture decision record describing Deck as a reusable host for operational panels.
    • Added a draft specification for an operator cockpit covering service health, cost monitoring, Cosmos exploration, migration management, and batch-run monitoring.
    • Documented integration contracts, readiness states, secret handling, graceful degradation, and known extraction gaps.

Lands the detailed spec and ADR that baton task 0e6c0c19 has been blocked
on ("NEXT: detailed spec + ADR required before build"). Both were authored
2026-07-11 and had lived only as untracked files in a working tree since.

- docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md (Proposed)
  Records the decision that deck stays a generic panel-host and Mystira ops
  tooling is hosted as bounded, omissible panel modules on top of it, rather
  than folding Mystira surfaces into the shell or building the cockpit
  elsewhere. Establishes docs/adr/NNNN-*.md as deck's ADR home.

- docs/specs/deck-ops-cockpit.md (Draft)
  Technical design for the three R13 facets: a Dashboard cost/ops section
  (sluice health + docket spend), the Cosmos Explorer + Migration Manager
  re-port, and a Service-Manager story-gen batch-run monitor. Establishes
  docs/specs/ as the home for deck design specs.

Re-grounded against dev @ bc0d1c5 before commit. The design is unchanged;
the current-state evidence was corrected where deck moved since July:

- §1.2 claimed the frontend could not typecheck because AppContent.tsx and
  AppSidebar.tsx still imported the removed panels. PR #3 removed that
  wiring and PR #5's CI proves the build is green. The finding is kept in
  corrected form — the extraction is still unfinished, but the evidence is
  now behavioural: three dead Dashboard quick-actions that fall through to
  the Service Manager, orphaned StatisticsPanel/ExportPanel callers, and
  live Rust/.NET backends with no UI above them.
- §1.1 now records crates/deck-camera and the CI gates, and cites the
  Camera panel as the four-file recipe's most recent worked example.
- §1.4/§1.2 line references refreshed; get_cli_executable_path() is in
  helpers.rs, not cli.rs.

Docs-only: no code, no CI surface touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@JustAGhosT, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e3ef69e-6a29-4090-996a-bc09efe02b34

📥 Commits

Reviewing files that changed from the base of the PR and between 48638f9 and 254e542.

📒 Files selected for processing (1)
  • docs/specs/deck-ops-cockpit.md
📝 Walkthrough

Walkthrough

Added ADR-0001 and a draft specification for using Deck as a generic host for Mystira operations panels. The specification covers Dashboard monitoring, Cosmos and migration tooling, story-generator batch operations, security, readiness, and integration prerequisites.

Changes

Mystira operations cockpit

Layer / File(s) Summary
Panel-host architecture
docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md
Defines Deck’s generic shell, bounded Mystira panels, external service contracts, secret handling, extraction requirements, and rejected alternatives.
Cockpit integration contract
docs/specs/deck-ops-cockpit.md
Defines the integration recipe, extraction gaps, CI constraints, secret handling, and naming and CLI-path cleanup.
Operations facets
docs/specs/deck-ops-cockpit.md
Specifies Dashboard monitoring for sluice and docket, Cosmos Explorer and Migration Manager panels, and Service Manager batch-run operations for story-generator.
Readiness and security requirements
docs/specs/deck-ops-cockpit.md
Defines security controls, capability readiness states, build order, cross-repository dependencies, extraction prerequisites, and the companion ADR reference.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes both documentation artifacts added by the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/deck-ops-cockpit-spec-and-adr

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md`:
- Around line 56-60: Align the ADR’s plugin-boundary description with the
four-file panel recipe: either specify an actual registry/plugin mechanism, or
state that Mystira panels are build-time modules requiring registration changes
in constants.ts, App.tsx, AppContent.tsx, and AppSidebar.tsx. Remove or revise
claims that panels can be omitted without touching the shell and that VIEWS is
the sole shared touch-point, including the corresponding statements in the
referenced sections.

In `@docs/specs/deck-ops-cockpit.md`:
- Line 86: Remove the blank line within the blockquote in the drift note section
of the document, keeping the note contiguous with the surrounding blockquote
content or moving it outside the blockquote.
- Around line 153-160: Resolve the `/metrics` authentication ambiguity in the
deck-ops cockpit specification by selecting one deployed contract. Update the
signal table and related readiness or cross-repo dependency references
consistently, and document credential provisioning plus readiness behavior if
scrape-scoped authentication is selected.
- Around line 232-233: Update the Section 3.2 command plan around sluice_health
to expose a distinct sluice_liveliness command and corresponding DTO for
/health/liveliness, while retaining sluice_health for /health/readiness;
alternatively, explicitly aggregate both endpoints under the existing command
with documented targets.
- Around line 422-426: Update the docket MCP entry to use a single verified
status consistent with the stated built, deployed, and registered state; remove
the contradictory “specced, not built” wording while preserving the listed
tools, deployment details, registration, and references.
- Around line 390-392: Update the Rust command and service-health HTTP paths
using reqwest to enforce HTTPS and allow only the configured sluice, docket, and
story-gen hosts. Reject any destination outside that host allow-list, and ensure
check_service_health does not enable danger_accept_invalid_certs(true); preserve
the existing Tauri capability scope.
- Around line 320-331: Define explicit request and response types for POST
api/stories/batch and GET api/stories/batch/{operationId}, replacing the
undefined BatchOperation and keeping BatchGenerationItem distinct from
BatchSubmission. Reuse GeneratorConfig from story_generator.rs for supported
fields, defaults, and validation; document the submit-phase trigger contract,
kill-switch write semantics, and POST idempotency keyed by custom_id ==
BatchGenerationItem.Id.
- Around line 209-211: Update the docket /mcp request configuration to validate
the resolved endpoint before attaching the DOCKET_MCP_TOKEN bearer: require
HTTPS and an allowlisted base host, including the configured default and
approved override. Reject invalid endpoint overrides and do not send the
Authorization header when validation fails.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fc8dbe2c-fbac-4a49-840f-2c2e84e410e1

📥 Commits

Reviewing files that changed from the base of the PR and between bc0d1c5 and 48638f9.

📒 Files selected for processing (2)
  • docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md
  • docs/specs/deck-ops-cockpit.md

Comment on lines +56 to +60
3. **deck is a generic panel-host; Mystira panels are pluggable, clearly-bounded modules.** The
shell (VSCode layout, activity bar, Service Manager, Infrastructure panel, exec primitives,
.NET sidecar bridge) stays generic and org-agnostic; Mystira-specific surfaces are added through
the existing four-file panel recipe as **cohesive, self-contained modules** that consume
external Mystira/phoenixvc contracts and can be omitted without touching the shell.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Align the plugin boundary with the actual panel recipe.

The ADR says Mystira modules can be omitted without touching the shell and that VIEWS is the only shared touch-point. The companion specification requires changes to constants.ts, App.tsx, AppContent.tsx, and AppSidebar.tsx for each panel. Either define a real registry/plugin mechanism, or describe these as build-time modules that require shell registration.

Proposed wording adjustment
- can be omitted without touching the shell.
+ can be omitted through build-time panel registration; the current recipe requires explicit shell registration.

Also applies to: 73-77, 110-113

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/adr/0001-deck-as-panel-host-for-mystira-ops-tooling.md` around lines 56
- 60, Align the ADR’s plugin-boundary description with the four-file panel
recipe: either specify an actual registry/plugin mechanism, or state that
Mystira panels are build-time modules requiring registration changes in
constants.ts, App.tsx, AppContent.tsx, and AppSidebar.tsx. Remove or revise
claims that panels can be omitted without touching the shell and that VIEWS is
the sole shared touch-point, including the corresponding statements in the
referenced sections.

Comment thread docs/specs/deck-ops-cockpit.md Outdated
Comment on lines +153 to +160
| Signal | Source | Endpoint | Auth | Transport |
| --- | --- | --- | --- | --- |
| Gateway liveness | sluice | `GET https://sluice.phoenixvc.tech/health/liveliness` | **none** | Rust `cost.rs` (reqwest) |
| Gateway readiness (db, litellm version, callbacks) | sluice | `GET …/health/readiness` → JSON | **none** | Rust `cost.rs` |
| Throughput / request rollups | sluice | `GET …/metrics` (Prometheus text) | **none** (or scrape-scoped) | Rust `cost.rs` — parse Prometheus |
| Spend summary / by-service / burn / trend | **docket MCP** | `get_burn_total`, `get_spend_by_service`, `get_cost_trend`, `get_ai_spend` | `MCP_SECRET` Bearer | see §3.3 |
| Optimization insights | docket MCP | `get_optimization_insights` | `MCP_SECRET` Bearer | see §3.3 |
| Per-component LLM spend | docket MCP | `get_llm_usage_by_component` | `MCP_SECRET` Bearer | **gated** — §7 of the docket spec |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file exists and relevant ranges =="
if [ -f docs/specs/deck-ops-cockpit.md ]; then
  wc -l docs/specs/deck-ops-cockpit.md
  sed -n '130,180p' docs/specs/deck-ops-cockpit.md | cat -n
  sed -n '380,430p' docs/specs/deck-ops-cockpit.md | cat -n
else
  echo "docs/specs/deck-ops-cockpit.md not found"
  fd -a 'deck-ops-cockpit.md|cockpit|deck-ops' .
fi

echo
echo "== search metrics/auth/readiness mentions =="
rg -n "metrics|readiness|liveliness|scrape|Authentication|auth|Bearer|Authorization|MCP_SECRET|health" docs/specs/deck-ops-cockpit.md || true

Repository: phoenixvc/deck

Length of output: 12076


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository files mentioning /metrics or health endpoints =="
rg -n "/metrics|health/liveliness|health/readiness|readiness|liveliness|get_burn_total|MCP_SECRET" . --glob '!node_modules' --glob '!dist' --glob '!build' --glob '!out' --glob '!coverage' | head -200 || true

Repository: phoenixvc/deck

Length of output: 3705


Resolve the /metrics authentication contract before declaring Facet 1 buildable.

The spec allows /metrics to be either unauthenticated or scrape-scoped, while the readiness tables and cross-repo dependency list treat the full health + throughput path as unauthenticated. Pick one deployed contract and document credential provisioning/readiness behavior if auth is required.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/specs/deck-ops-cockpit.md` around lines 153 - 160, Resolve the
`/metrics` authentication ambiguity in the deck-ops cockpit specification by
selecting one deployed contract. Update the signal table and related readiness
or cross-repo dependency references consistently, and document credential
provisioning plus readiness behavior if scrape-scoped authentication is
selected.

Comment on lines +209 to +211
- **Endpoint config:** the docket `/mcp` base URL and the sluice base URL are non-secret and can
live in `Deck.CLI/appsettings.json` / deck app-config with env-override, defaulting to
`https://sluice.phoenixvc.tech` and the docket Railway `/mcp` URL.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate spec and docket references =="
fd -a 'deck-ops-cockpit.md' . || true
rg -n "DOCKET_MCP_TOKEN|mcp|Docket|Bearer|Authorization|sluice|appsettings" . -S --glob '!**/.git/**' --glob '!node_modules/**' | head -200

echo "== spec context =="
if [ -f docs/specs/deck-ops-cockpit.md ]; then
  sed -n '180,230p' docs/specs/deck-ops-cockpit.md | cat -n
fi

Repository: phoenixvc/deck

Length of output: 13725


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository files likely containing docket/MCP cost client =="
git ls-files | rg '^(app/src-tauri|Deck\.CLI|docs/specs/07_docket_mcp_server\.md|docs/specs/deck-ops-cockpit\.md)' | sed -n '1,120p'

echo "== cost/docket/mcp token references in tracked files =="
rg -n "DOCKET_MCP_TOKEN|MCP_SECRET|docket .*mcp|/mcp|Authorization: Bearer|Authorization: bearer|requests\.post|client\.post|HttpClient|reqwest|AppSettings|Docket" $(git ls-files | tr '\n' ' ') -S --glob '!*node_modules/**' | sed -n '1,220p'

Repository: phoenixvc/deck

Length of output: 5237


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== inspect existing auth/header usage patterns in Rust source =="
rg -n "Authorization|bearer|Bearer|reqwest::Client|allow_redirects|https://|http://" app/src-tauri/src -S --glob '*.rs' | sed -n '1,240p'

echo "== inspect relevant Rust source slices =="
for f in app/src-tauri/src/cosmos.rs app/src-tauri/src/github.rs app/src-tauri/src/utils.rs app/src-tauri/src/config.rs; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    sed -n '1,260p' "$f" | cat -n
  fi
done

Repository: phoenixvc/deck

Length of output: 43998


Do not send the bearer to an arbitrary endpoint.

Endpoint config is allowlisted as non-secret, but the docket /mcp calls still send Authorization: Bearer <DOCKET_MCP_TOKEN>. Validate that the resolved URL uses https and an approved base host before adding the bearer header; reject invalid overrides.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/specs/deck-ops-cockpit.md` around lines 209 - 211, Update the docket
/mcp request configuration to validate the resolved endpoint before attaching
the DOCKET_MCP_TOKEN bearer: require HTTPS and an allowlisted base host,
including the configured default and approved override. Reject invalid endpoint
overrides and do not send the Authorization header when validation fails.

Comment on lines +232 to +233
#[tauri::command] pub async fn sluice_health() -> Result<SluiceHealth, String>; // GET /health/readiness
#[tauri::command] pub async fn sluice_metrics() -> Result<SluiceMetrics, String>; // GET /metrics (Prometheus parse)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Find target file:"
fd -a "deck-ops-cockpit.md" . || true

echo
echo "Target context if found:"
while IFS= read -r f; do
  echo "--- $f"
  wc -l "$f"
  sed -n '200,260p' "$f"
done < <(fd "deck-ops-cockpit.md" .)

echo
echo "Search for health/liveliness/readiness references:"
rg -n "/health/(liveliness|readiness)|sluice_health|liveliness|readiness" . || true

Repository: phoenixvc/deck

Length of output: 299


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Target context:"
wc -l docs/specs/deck-ops-cockpit.md
sed -n '200,260p' docs/specs/deck-ops-cockpit.md

echo
echo "Search health references:"
rg -n "/health/(liveliness|readiness)|sluice_health|liveliness|readiness" docs/specs/deck-ops-cockpit.md . || true

Repository: phoenixvc/deck

Length of output: 5649


Expose sluice_liveliness alongside readiness.

Section 3.2 depends on /health/liveliness, but the cost.rs command plan only maps sluice_health to /health/readiness. Add a liveness command/DTO, or rename/aggregate it with an explicit /health/liveliness target.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/specs/deck-ops-cockpit.md` around lines 232 - 233, Update the Section
3.2 command plan around sluice_health to expose a distinct sluice_liveliness
command and corresponding DTO for /health/liveliness, while retaining
sluice_health for /health/readiness; alternatively, explicitly aggregate both
endpoints under the existing command with documented targets.

Comment on lines +320 to +331
### 5.2 Design against the specced operation-id + status model

From `BATCH_API_GENERATION_ROUTING.md` (R13, Draft — **not yet built**), the model deck renders
against:

- **Enqueue → operation id.** A bulk request returns an **operation id immediately (202)**, exactly
like the continuity async pattern. `custom_id == BatchGenerationItem.Id`.
- **Item status ladder:** `Queued → Submitted → Succeeded | Errored | Expired | Failed` (with
`BatchId msgbatch_…`, `SubmittedAt`, `CompletedAt`, `Attempts`).
- **Batch status:** `BatchSubmission { BatchId, WindowId (batch-YYYYMMDD), ItemCount,
ProcessingStatus (in_progress|canceling|ended), Counts { processing, succeeded, errored,
canceled, expired } }`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repo files around deck contracts and doc:"
git ls-files | rg '(^docs/specs/deck-ops-cockpit\.md$|BATCH_API_GENERATION_ROUTING\.md$|story_generator\.rs$|deck-contracts|batch|operation)' || true

echo
echo "Target doc section:"
if [ -f docs/specs/deck-ops-cockpit.md ]; then
  wc -l docs/specs/deck-ops-cockpit.md
  sed -n '300,380p' docs/specs/deck-ops-cockpit.md | cat -n -v
fi

echo
echo "Search BatchOperation and related symbols:"
rg -n "BatchOperation|BatchGenerationItem|BatchSubmission|GeneratorConfig|POST .*202|202|trigger|kill|cancel|idempot" -S . || true

Repository: phoenixvc/deck

Length of output: 19905


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Story generator contract:"
cat -n crates/deck-contracts/src/story_generator.rs | sed -n '1,240p'

echo
echo "Any Batch Generation model refs in repository text only:"
python3 - <<'PY'
import subprocess, re, pathlib
files = subprocess.check_output(['git','ls-files'], text=True).splitlines()
patterns = [
    re.compile(r'\b(BatchGenerationItem|BatchSubmission|GeneratorConfig|BatchOperation|BatchEnqueueRequest)\b'),
    re.compile(r'\b(POST api/stories/batch|GET api/stories/batch/\{operationId\}|202|idempot|kill|cancel)\b', re.I),
]
for path in files:
    text = pathlib.Path(path).read_text(errors='ignore')
    hits = [f"{m.group(1)} ({text.count(m.group(1))})" for m in patterns[0].finditer(text) if m.group(1)]
    status_hits = set(re.findall(r'(\b(?:POST api/stories/batch|GET api/stories/batch/\{operationId\}|202|idempot|kill|cancel)\b)', text, re.I))
    if hits or status_hits:
        print(f"--- {path} ---")
        for hit in sorted(set(hits)):
            print("symbol", hit)
        if status_hits:
            print("signals", ", ".join(sorted(status_hits)))
        print()
PY

Repository: phoenixvc/deck

Length of output: 8661


Define the batch command contract before implementation.

POST api/stories/batch and GET api/stories/batch/{operationId} currently return the undefined BatchOperation. Add the exact request/response types; it should not contain both BatchGenerationItem and BatchSubmission, which have different meanings. Reuse GeneratorConfig from crates/deck-contracts/src/story_generator.rs for supported fields, defaults, and validation. Also define the submit-phase trigger contract, kill-switch write semantics, and POST idempotency for custom_id == BatchGenerationItem.Id.

Also applies to: 336-362

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/specs/deck-ops-cockpit.md` around lines 320 - 331, Define explicit
request and response types for POST api/stories/batch and GET
api/stories/batch/{operationId}, replacing the undefined BatchOperation and
keeping BatchGenerationItem distinct from BatchSubmission. Reuse GeneratorConfig
from story_generator.rs for supported fields, defaults, and validation; document
the submit-phase trigger contract, kill-switch write semantics, and POST
idempotency keyed by custom_id == BatchGenerationItem.Id.

Comment on lines +390 to +392
- **argv-only + minimal capabilities.** New backend commands use `Command::new`/reqwest with no
shell interpolation; outbound HTTP to sluice/docket/story-gen is added as an explicit Tauri
capability, not a blanket network grant.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

rg -n 'reqwest|plugin-http|http:default|capabilities' app/src-tauri crates

Repository: phoenixvc/deck

Length of output: 481


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- app/src-tauri/Cargo.toml dependencies/packages ---\n'
cat -n app/src-tauri/Cargo.toml | sed -n '1,80p'

printf '\n--- capabilities/default.json ---\n'
cat -n app/src-tauri/Capabilities/default.json 2>/dev/null || cat -n app/src-tauri/capabilities/default.json | sed -n '1,220p'

printf '\n--- reqwest usage in utils.rs ---\n'
cat -n app/src-tauri/src/utils.rs | sed -n '300,355p'

printf '\n--- reqwest usage in status.rs ---\n'
cat -n app/src-tauri/src/services/status.rs | sed -n '1,90p'

printf '\n--- spec relevant lines ---\n'
cat -n docs/specs/deck-ops-cockpit.md | sed -n '370,405p'

printf '\n--- files cost/story names ---\n'
fd -i 'cost|story_gen|status|utils' app/src-tauri -t f

Repository: phoenixvc/deck

Length of output: 243


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- app/src-tauri/Cargo.toml dependencies/packages ---'
cat -n app/src-tauri/Cargo.toml | sed -n '1,80p'

printf '%s\n' ''
printf '%s\n' '--- capabilities/default.json ---'
if [ -f app/src-tauri/Capabilities/default.json ]; then
  cat -n app/src-tauri/Capabilities/default.json | sed -n '1,220p'
else
  cat -n app/src-tauri/capabilities/default.json | sed -n '1,220p'
fi

printf '%s\n' ''
printf '%s\n' '--- reqwest usage in utils.rs ---'
cat -n app/src-tauri/src/utils.rs | sed -n '300,355p'

printf '%s\n' ''
printf '%s\n' '--- reqwest usage in status.rs ---'
cat -n app/src-tauri/src/services/status.rs | sed -n '1,90p'

printf '%s\n' ''
printf '%s\n' '--- spec relevant lines ---'
cat -n docs/specs/deck-ops-cockpit.md | sed -n '370,405p'

printf '%s\n' ''
printf '%s\n' '--- files cost/story names ---'
fd -i 'cost|story_gen|status|utils' app/src-tauri -t f

Repository: phoenixvc/deck

Length of output: 9740


Enforce and allow-list native reqwest destinations.

This app uses native reqwest for command and service-health HTTP, but the Tauri capability is shell/opener/FS focused and has no HTTP plugin permissions. Add native allow-list checks in the Rust commands: require HTTPS and only permit configured sluice/docket/story-gen hosts, including rejected danger_accept_invalid_certs(true) in check_service_health.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/specs/deck-ops-cockpit.md` around lines 390 - 392, Update the Rust
command and service-health HTTP paths using reqwest to enforce HTTPS and allow
only the configured sluice, docket, and story-gen hosts. Reject any destination
outside that host allow-list, and ensure check_service_health does not enable
danger_accept_invalid_certs(true); preserve the existing Tauri capability scope.

Source: MCP tools

Comment on lines +422 to +426
1. **docket MCP** (`phoenixvc/docket`) — Phase-1 tools built (`get_burn_total`,
`get_spend_by_service`, `get_cost_trend`, `get_ai_spend`, `get_spend_by_resource_group`,
`get_spend_by_region`), deployed on Railway behind `MCP_SECRET`, and **registered in the org
MCP** (`register_project`). Status: **specced, not built** (spec `07_docket_mcp_server.md`,
ADR-09; baton `91ca9c86-4057-49ad-8d2e-4744188daee1`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | rg 'docs/specs/deck-ops-cockpit\.md|07_docket_mcp_server\.md|ADR-09|baton|docket|cockpit' | head -200

echo
echo "== target excerpt =="
if [ -f docs/specs/deck-ops-cockpit.md ]; then
  nl -ba docs/specs/deck-ops-cockpit.md | sed -n '405,435p'
else
  echo "target file not found"
fi

echo
echo "== search for docket status/status-related terms and baton =="
rg -n "docket|specced, not built|Phase-1|Phase 1|baton|91ca9c86-4057-49ad-8d2e-4744188daee1|register_project|mcp_secret|MCP_SECRET" docs/specs docs 2>/dev/null | head -200

Repository: phoenixvc/deck

Length of output: 264


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target excerpt =="
awk 'NR>=405 && NR<=435 {printf "%7d\t%s\n", NR, $0}' docs/specs/deck-ops-cockpit.md

echo
echo "== search for docket references, status, and baton =="
rg -n "docket|specced, not built|Phase-1|Phase 1|baton|91ca9c86-4057-49ad-8d2e-4744188daee1|register_project|MCP_SECRET|07_docket_mcp_server\.md|ADR-09" docs/specs docs 2>/dev/null | head -200 || true

Repository: phoenixvc/deck

Length of output: 19082


Use one status for the docket dependency.

Lines 407 and 422-425 say the docket MCP tools are built, deployed, and registered; line 425 then says its status is “specced, not built.” This contradicts the Facet 1 readiness statement and the build order. Replace the dependency status with one verified status.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/specs/deck-ops-cockpit.md` around lines 422 - 426, Update the docket MCP
entry to use a single verified status consistent with the stated built,
deployed, and registered state; remove the contradictory “specced, not built”
wording while preserving the listed tools, deployment details, registration, and
references.

Follow-up to CodeRabbit review on PR #6. Three changes, all current-state
accuracy — the design and both decisions are unchanged.

- §1.3 claimed outbound HTTP to sluice/docket would be "an explicit
  capability addition". That is wrong: deck calls out via native reqwest
  from Rust, not the Tauri HTTP plugin, so capabilities/default.json
  (shell/opener/dialog/fs only) does not constrain it. The spec's own
  security posture was resting on a mechanism that does not apply. Now
  states the real requirement — per-command https + host allowlisting
  enforced in Rust — and flags that services/status.rs:44 sets
  danger_accept_invalid_certs(true) for localhost, which the cockpit's
  clients must not reuse against remote endpoints.
- §5.4 introduced a BatchOperation type without noting that
  crates/deck-contracts/src/story_generator.rs already exists and is the
  natural home for it. Records that, and that BatchGenerationItem and
  BatchSubmission must stay distinct per §5.2.
- §1.2 fixes MD028 (blank line inside blockquote) introduced by the
  drift note in the previous commit.

Not changed, and left for the owner as review feedback on a Draft spec:
the /metrics auth contract, the missing sluice_liveliness command, and
the ADR's "omitted without touching the shell" wording vs the four-file
recipe (the ADR already books this under Negative/Costs). The reported
§7/§8 docket-status contradiction is a misread — §8 lists what must
become real, then states current status; the two agree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@JustAGhosT
JustAGhosT merged commit 5e8c42b into dev Aug 10, 2026
3 checks passed
@JustAGhosT
JustAGhosT deleted the docs/deck-ops-cockpit-spec-and-adr branch August 10, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant