Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions src/channels/web/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Browser-facing HTTP API and SSE/WebSocket real-time streaming. Axum-based, singl
| File | Role |
|------|------|
| `mod.rs` | Gateway builder, startup, `WebChannel` implementation, `with_*` builder methods |
| `server.rs` | `start_server()`, Axum route registrations, and feature handlers that have not yet moved (OAuth callbacks, chat, extensions, pairing, logs, gateway status). Re-exports `GatewayState` and friends from `platform::state` for backward compatibility during the ironclaw#2599 migration. |
| `server.rs` | Feature handlers that have not yet moved (OAuth callbacks, chat, extensions, pairing, logs, gateway status). Re-exports `GatewayState` / `start_server` / related types from `platform::*` for backward compatibility during the ironclaw#2599 migration. |
| `platform/router.rs` | `start_server()` + Axum route composition (public / protected / statics / projects) and the cross-cutting layer stack (CORS, body limit, panic catch, static security headers, CSP). Single coupling point between platform and features. |
| `platform/state.rs` | `GatewayState`, `RateLimiter`, `PerUserRateLimiter`, `WorkspacePool`, `FrontendHtmlCache`, `FrontendCacheKey`, `ActiveConfigSnapshot`, `PromptQueue`, `RoutineEngineSlot`. Canonical home for shared gateway state. |
Comment on lines 9 to 12

Copilot AI Apr 18, 2026

Copy link

Choose a reason for hiding this comment

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

The file map now describes platform/router.rs as the coupling point between platform and features, but the later "Platform vs. feature layering" section still states the platform/ subtree has "no back-edges". Please reconcile the layering docs so readers understand whether the router is an exception or the rule has changed.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in 31735cc. Rewrote the "Platform vs. feature layering" section in CLAUDE.md to reconcile with the File Map: router is the coupling point; every other platform submodule must stay handler-agnostic; the CI check planned for ironclaw#2599 stage 5 will forbid cross-imports between platform/{state,static_files,auth,sse,ws}.rs and handlers/* / features/* while explicitly allowing platform/router.rs to reference both sides.

| `platform/static_files.rs` | CSP directive set + `BASE_CSP_HEADER` (single source of truth), frontend HTML bundle assembly (`build_frontend_html`), and the unauthenticated static handlers: `/`, `/style.css`, `/app.js`, `/theme.css`, `/favicon.ico`, `/i18n/*`, `/admin*`, `/api/health`, plus the authenticated `/projects/{id}/...` file-serving routes. |
| `types.rs` | Request/response DTOs and `SseEvent` enum (source of truth for SSE contract) |
Expand All @@ -22,15 +23,26 @@ Browser-facing HTTP API and SSE/WebSocket real-time streaming. Axum-based, singl

## Platform vs. feature layering (ironclaw#2599)

The target layout is a `platform/` subtree (router, state, auth, SSE, WS,
static serving) that feature handlers depend on, with no back-edges. The
flat `handlers/` folder is a transitional fallback — individual handlers
will migrate into `features/<slice>/` directories once their platform
dependencies are narrowed to a per-slice `Deps` view. When adding a new
platform-level concern, put it under `platform/`; when adding a new
feature handler, keep it under `handlers/` for now but design it so the
surface it consumes from `GatewayState` is a narrow subset that can
later be replaced by a typed `Deps` alias.
The target layout is a `platform/` subtree (router, state, auth, SSE,
WS, static serving) that feature handlers depend on.

**The "no back-edges" rule has one intentional exception: the router.**
Route composition is inherently the coupling point where transport
meets features — `platform/router.rs` imports every feature handler it
registers. Every *other* platform submodule (state, static_files, and
the auth/SSE/WS modules once they move) must stay handler-agnostic,
and that's what the future CI check (ironclaw#2599 stage 5) will
enforce: forbid cross-imports between `platform/{state,static_files,
auth,sse,ws}.rs` and `handlers/*` / `features/*`, but allow
`platform/router.rs` to reference both sides.

The flat `handlers/` folder is a transitional fallback — individual
handlers will migrate into `features/<slice>/` directories once their
platform dependencies are narrowed to a per-slice `Deps` view. When
adding a new platform-level concern, put it under `platform/`; when
adding a new feature handler, keep it under `handlers/` for now but
design it so the surface it consumes from `GatewayState` is a narrow
subset that can later be replaced by a typed `Deps` alias.

## API Routes

Expand Down
16 changes: 13 additions & 3 deletions src/channels/web/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
//!
//! This submodule holds the gateway's transport and framing concerns: shared
//! state, the Axum route composition, static asset serving, and (in later
//! stages of ironclaw#2599) auth / SSE / WS. Feature-specific handlers live
//! alongside their domain (`handlers/` today, `features/<slice>/` in later
//! stages) and depend on the platform layer, not the other way around.
//! stages of ironclaw#2599) auth / SSE / WS.
//!
//! **Dependency direction.** Feature handlers (under `handlers/` today,
//! `features/<slice>/` later) depend on platform types (`GatewayState`,
//! rate limiters, auth extractors). Platform *submodules* do **not**
//! reach back into feature handlers — with the single, intentional
//! exception of [`router`], which is the composition point. The router
//! imports every feature handler it registers; that is its job. The
//! "no back-edges" rule enforced by future CI (ironclaw#2599 stage 5)
//! applies to `platform/state.rs`, `platform/static_files.rs`, and the
//! auth/SSE/WS modules once they move here — not to `router`, whose
//! whole purpose is to wire features onto the transport.
//!
//! See `src/channels/web/CLAUDE.md` for the staged migration plan.

pub mod router;
pub mod state;
pub mod static_files;
Loading
Loading