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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ jobs:
- name: Validate i18n keys
run: npm run validate:i18n

- name: Validate framework scope
run: node scripts/validate-framework-scope.mjs

- name: TypeScript type check
run: npm run typecheck

Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ HTTP load tests using real OAuth Bearer tokens acquired via ROPC (password grant

- **ClientApp** (`template/SimpleModule.Host/ClientApp/app.tsx`) — Inertia bootstrap. Resolves pages by splitting route name (e.g., `Products/Browse` → imports `/_content/Products/Products.pages.js`).
- **Module pages** — Each module builds its React pages via Vite in library mode → `{ModuleName}.pages.js` in module's `wwwroot/`. Entry point: `Pages/index.ts` exporting a `pages` record mapping route names to components.
- **Type generation** — `[Dto]` types → source generator embeds TS interfaces → `tools/extract-ts-types.mjs` writes `.ts` files to `ClientApp/types/`.
- **Type generation** — `[Dto]` types → source generator embeds TS interfaces → `scripts/extract-ts-types.mjs` writes `.ts` files to `ClientApp/types/`.

### Request Flow

Expand Down
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<PackageVersion Include="WolverineFx" Version="5.31.0" />
<PackageVersion Include="Scrutor" Version="7.0.0" />
<!-- Email -->
<PackageVersion Include="MailKit" Version="4.15.1" />
<PackageVersion Include="MailKit" Version="4.16.0" />
<!-- CLI -->
<PackageVersion Include="Spectre.Console.Cli" Version="0.49.1" />
<!-- AI / LLM Providers -->
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ COPY framework/SimpleModule.Core/*.csproj framework/SimpleModule.Core/
COPY framework/SimpleModule.Database/*.csproj framework/SimpleModule.Database/
COPY framework/SimpleModule.Generator/*.csproj framework/SimpleModule.Generator/
COPY framework/SimpleModule.Hosting/*.csproj framework/SimpleModule.Hosting/
COPY framework/SimpleModule.DevTools/*.csproj framework/SimpleModule.DevTools/
COPY tools/SimpleModule.DevTools/*.csproj tools/SimpleModule.DevTools/
COPY framework/SimpleModule.Storage/*.csproj framework/SimpleModule.Storage/
COPY framework/SimpleModule.Storage.Local/*.csproj framework/SimpleModule.Storage.Local/
COPY framework/SimpleModule.Storage.Azure/*.csproj framework/SimpleModule.Storage.Azure/
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.worker
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ WORKDIR /src

# Node is needed in the build stage (not at runtime) because the
# ExtractDtoTypeScript / ExtractRoutes targets in SimpleModule.Hosting.targets
# shell out to `node tools/extract-*.mjs` after CoreCompile. The scripts only
# shell out to `node scripts/extract-*.mjs` after CoreCompile. The scripts only
# use Node stdlib, so no `npm ci` — just the node binary.
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl \
Expand All @@ -32,7 +32,7 @@ COPY framework/SimpleModule.Core/*.csproj framework/SimpleModule.Core/
COPY framework/SimpleModule.Database/*.csproj framework/SimpleModule.Database/
COPY framework/SimpleModule.Generator/*.csproj framework/SimpleModule.Generator/
COPY framework/SimpleModule.Hosting/*.csproj framework/SimpleModule.Hosting/
COPY framework/SimpleModule.DevTools/*.csproj framework/SimpleModule.DevTools/
COPY tools/SimpleModule.DevTools/*.csproj tools/SimpleModule.DevTools/
COPY framework/SimpleModule.Storage/*.csproj framework/SimpleModule.Storage/
COPY framework/SimpleModule.Storage.Local/*.csproj framework/SimpleModule.Storage.Local/
COPY framework/SimpleModule.Storage.Azure/*.csproj framework/SimpleModule.Storage.Azure/
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ template/
cli/
SimpleModule.Cli # `sm` CLI tool for scaffolding and validation
tests/ # Framework tests, shared test infrastructure, and e2e tests
tools/ # Build/dev orchestrators, type extraction, component scaffolding
scripts/ # Build/dev orchestrators, type extraction, component scaffolding
```

### Request Flow
Expand Down
4 changes: 3 additions & 1 deletion SimpleModule.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<Project Path="framework/SimpleModule.Core/SimpleModule.Core.csproj" />
<Project Path="framework/SimpleModule.Generator/SimpleModule.Generator.csproj" />
<Project Path="framework/SimpleModule.Database/SimpleModule.Database.csproj" />
<Project Path="framework/SimpleModule.DevTools/SimpleModule.DevTools.csproj" />
<Project Path="framework/SimpleModule.Hosting/SimpleModule.Hosting.csproj" />
<Project Path="framework/SimpleModule.Storage/SimpleModule.Storage.csproj" />
<Project Path="framework/SimpleModule.Storage.Local/SimpleModule.Storage.Local.csproj" />
Expand All @@ -27,6 +26,9 @@
<Folder Name="/cli/">
<Project Path="cli/SimpleModule.Cli/SimpleModule.Cli.csproj" />
</Folder>
<Folder Name="/tools/">
<Project Path="tools/SimpleModule.DevTools/SimpleModule.DevTools.csproj" />
</Folder>
<Folder Name="/modules/" />
<Folder Name="/modules/Dashboard/">
<Project Path="modules/Dashboard/src/SimpleModule.Dashboard.Contracts/SimpleModule.Dashboard.Contracts.csproj" />
Expand Down
37 changes: 37 additions & 0 deletions docs/CONSTITUTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,40 @@ All SM diagnostics are emitted by the Roslyn source generator at compile time. `
- `AnalysisLevel=latest-all`, `AnalysisMode=All`.
- Suppressed rules live in `.editorconfig`.
- Tests run against both SQLite and PostgreSQL in CI.

---

## 13. Framework Scope

The `framework/` directory contains foundational plumbing: module lifecycle, source generation, DbContext infrastructure, and host bootstrap. Nothing else.

Framework projects are explicitly allowlisted in `framework/.allowed-projects`. The target list contains exactly: `SimpleModule.Core`, `SimpleModule.Database`, `SimpleModule.Generator`, `SimpleModule.Hosting`. During the in-flight migration, the list is temporarily permissive and shrinks as projects migrate.

### Adding a project to `framework/`

Requires:

1. Justification that the project is foundational — referenced by the host bootstrap or by every module, with no domain or provider semantics.
2. A PR that updates `.allowed-projects`, names the reviewer, and documents why a module or `tools/` project is insufficient.

### `tools/` category

The `tools/` directory holds non-module .NET utilities consumed by the host, the framework bootstrap, or other tools. Rules:

- Flat layout: `tools/SimpleModule.{Name}/{Name}.csproj` — no `src/` subdirectory, no Contracts split.
- Tools never declare `[Module]`.
- Modules (anything under `modules/`) never reference a `tools/` project. The host and `framework/SimpleModule.Hosting` may.

### Sub-projects

A sub-project is an additional assembly inside a module, used when a module owns multiple optional providers (e.g., `SimpleModule.Agents.AI.Anthropic`). Rules:

- Lives at `modules/{Name}/src/SimpleModule.{Name}.{Suffix}/`.
- Name matches `SimpleModule.{Name}.{Suffix}`.
- Does not declare `[Module]` — only the main module assembly owns lifecycle.
- May not own a `DbContext`.
- Follows the same dependency rules as its module (Section 3).

### Enforcement

`scripts/validate-framework-scope.mjs` runs in CI and in `npm run check`. It fails on any violation of the rules above.
2 changes: 1 addition & 1 deletion docs/site/frontend/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ The `@simplemodule/client` package (`packages/SimpleModule.Client/`) provides th

## Type Safety

The source generator discovers C# types marked with the `[Dto]` attribute and embeds TypeScript interface definitions. The `tools/extract-ts-types.mjs` script extracts these into `.ts` files under `ClientApp/types/`, giving React components full type safety over server-provided props:
The source generator discovers C# types marked with the `[Dto]` attribute and embeds TypeScript interface definitions. The `scripts/extract-ts-types.mjs` script extracts these into `.ts` files under `ClientApp/types/`, giving React components full type safety over server-provided props:

```tsx
import type { Product } from '../types';
Expand Down
4 changes: 2 additions & 2 deletions docs/site/frontend/vite.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Three scripts are standard:

### `npm run dev`

The `npm run dev` command starts the complete development environment using the **dev orchestrator** (`tools/dev-orchestrator.mjs`). It launches three types of processes in parallel:
The `npm run dev` command starts the complete development environment using the **dev orchestrator** (`scripts/dev-orchestrator.mjs`). It launches three types of processes in parallel:

1. **`dotnet run`** -- The ASP.NET backend on `https://localhost:5001`
2. **Module watches** -- `vite build --watch` for every module with a `vite.config.ts`
Expand Down Expand Up @@ -197,7 +197,7 @@ npm run build

## Build Orchestrator

The production build uses the **build orchestrator** (`tools/build-orchestrator.mjs`) which:
The production build uses the **build orchestrator** (`scripts/build-orchestrator.mjs`) which:

1. Discovers all buildable workspaces (modules + ClientApp)
2. Builds all workspaces **in parallel** for performance
Expand Down
Loading
Loading