FullStack-Pilot / rules
Cursor rule2 starsChanged 4 months agoMITView on GitHub
Consolidated governance rules for full-stack Microsoft projects (Angular / .NET / SQL Server / Azure). Source: AgenticPawan/FullStack-Pilot plugin marketplace. For full skill depth, install the plugin: /plugin marketplace add AgenticPawan/FullStack-Pilot
We split this fullstack-pilot-rules.md into the rules it gives an agent
15 rules. About 0 are common, 4 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 12
All commits must follow <type>(<scope>): <subject> format.
- Distinctive: line 23
Never embed credentials, API keys, or connection strings in source files or IaC templates.
- Distinctive: line 34
Use named placeholders. Never interpolate variables directly into log message strings.
- Very specific: line 50
Never bind user-controlled content to [innerHTML].
- Very specific: line 51
If HTML is required, use DomSanitizer.bypassSecurityTrustHtml with a justification comment.
- Very specific: line 74
Use @if, @for, @switch built-in control flow.
- Very specific: line 99
Use concrete interfaces, unknown, or generics instead of : any.
- Very specific: line 102
Use signal() for local component state instead of plain properties.
- Very specific: line 128
Use Select() projections and AsNoTracking() for read queries.
- Very specific: line 129
Never call ToList() before Where/Select (client-side evaluation).
- Distinctive: line 141
All HTTP calls and external integrations must use a named resilience pipeline.
- Very specific: line 165
Use claim-based policies: policy.RequireClaim("permission", "orders:write").
- Distinctive: line 172
Never build SQL by string concatenation or interpolation into raw SQL strings.
- Very specific: line 196
All foreign key columns must have an index.
- Very specific: line 213
All production resources must have a CanNotDelete lock.
≈ “Common” is an estimate: at least 1 in 5 of the 6,350 Cursor rule files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
FullStack Pilot — Cursor Rules
Consolidated governance rules for full-stack Microsoft projects (Angular / .NET / SQL Server / Azure). Source: AgenticPawan/FullStack-Pilot plugin marketplace. For full skill depth, install the plugin:
/plugin marketplace add AgenticPawan/FullStack-Pilot
Cross-Stack (Always)
Conventional Commits
All commits must follow <type>(<scope>): <subject> format.
Types: feat, fix, docs, ci, chore, refactor, test, perf.
Breaking changes use ! suffix or BREAKING CHANGE: footer.
# BAD: "fix stuff" / "WIP" / "changes"
# GOOD: "fix(auth): handle token expiry before refresh window closes"No Hardcoded Secrets (OWASP-A02 — block)
Store secrets in environment variables, Azure Key Vault, or .NET user-secrets. Never embed credentials, API keys, or connection strings in source files or IaC templates.
// BAD — literal credential in source
// var conn = "Server=prod.database.windows.net;User=admin;Password=<literal>";
// GOOD — real value injected at runtime via Key Vault reference
var conn = builder.Configuration.GetConnectionString("Default");Structured Logging — No String Interpolation, PII Redacted (OWASP-A09)
Use named placeholders. Never interpolate variables directly into log message strings. Mask or omit PII fields (email, phone, card number).
// BAD
_logger.LogInformation($"User {user.Email} logged in from {ip}");
// GOOD
_logger.LogInformation("User {UserId} logged in from {IpHash}", user.Id, HashIp(ip));Angular / TypeScript
No [innerHTML] Without Justification (OWASP-A03 — block)
Never bind user-controlled content to [innerHTML]. Use text bindings by default.
If HTML is required, use DomSanitizer.bypassSecurityTrustHtml with a justification comment.
<!-- BAD -->
<div [innerHTML]="userContent"></div>
<!-- GOOD — use text binding -->
<div>{{ userContent }}</div>Permission-Based Authorization Only — No Role Checks (OWASP-A01 — block)
Route guards and structural directives must check a permission claim, never a role name. Client-side gating is UX only — the real authorization boundary is the .NET API.
// BAD
canActivate: [() => inject(AuthService).hasRole('Manager')]
// GOOD
canActivate: [() => inject(PermissionService).hasPermission('orders.approve')]Angular 17+ Control Flow (block on Angular 17+)
Use @if, @for, @switch built-in control flow. Do not use *ngIf, *ngFor, *ngSwitch in new components.
<!-- BAD (Angular 17+) -->
<div *ngIf="isLoading">...</div>
<li *ngFor="let item of items">...</li>
<!-- GOOD -->
@if (isLoading) { <div>...</div> }
@for (item of items; track item.id) { <li>...</li> }subscribe() Must Have Cleanup
All subscribe() calls in components must include takeUntilDestroyed(this.destroyRef) (Angular 16+) or use the async pipe. Uncleaned subscriptions are memory leaks.
// BAD
this.service.data$.subscribe(d => this.data = d);
// GOOD
this.service.data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(d => this.data = d);
// OR use: | async pipe in templateNo : any Type Bindings
Use concrete interfaces, unknown, or generics instead of : any. The any type defeats TypeScript's type system and breaks refactoring tools.
Signals for Local State (Angular 17+)
Use signal() for local component state instead of plain properties. Signals are required by future Zoneless Angular.
// BAD (Angular 17+)
isLoading = false;
// GOOD
isLoading = signal(false);.NET / C#
IHttpClientFactory — Never new HttpClient() (CWE-400 — block)
new HttpClient() causes socket exhaustion. Always inject via IHttpClientFactory.
// BAD
using var client = new HttpClient();
// GOOD — registered in Program.cs: builder.Services.AddHttpClient<MyService>();
public MyService(HttpClient client) => _client = client;EF Core — Projection-First, AsNoTracking() (warn)
Use Select() projections and AsNoTracking() for read queries.
Never call ToList() before Where/Select (client-side evaluation).
// BAD — loads entire table, filters in memory
var names = db.Products.ToList().Where(p => p.IsActive).Select(p => p.Name);
// GOOD
var names = await db.Products.AsNoTracking()
.Where(p => p.IsActive).Select(p => p.Name).ToListAsync(ct);Polly v8 Resilience Pipelines (block on .NET 8+)
All HTTP calls and external integrations must use a named resilience pipeline. Ad-hoc retry loops are a code-review block.
// GOOD — Program.cs
builder.Services.AddResiliencePipeline("payments", b => b
.AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 3 })
.AddTimeout(TimeSpan.FromSeconds(10))
.AddCircuitBreaker(new CircuitBreakerStrategyOptions()));No async void — Return Task
async void swallows exceptions. Return Task from all async methods. Exception: event handler delegates.
No .Result / .GetAwaiter().GetResult() — Await Throughout
.Result and .GetAwaiter().GetResult() deadlock ASP.NET Core request threads. Use await throughout the call chain.
No DateTime.Now — Use TimeProvider (.NET 8+)
DateTime.Now is untestable. Inject TimeProvider; use FakeTimeProvider in tests.
No Repository Pattern Wrapping EF Core (see ADR-003)
DbContext is the unit of work and repository. Do not wrap it in IXxxRepository interfaces. Inject AppDbContext directly.
Permissions-Only Authorization — No [Authorize(Roles = "...")]
Use claim-based policies: policy.RequireClaim("permission", "orders:write"). See ADR-001.
SQL Server / EF Core
Parameterized Queries Only (OWASP-A03, CWE-89 — block)
Never build SQL by string concatenation or interpolation into raw SQL strings.
// BAD
var sql = "SELECT * FROM Users WHERE Name = '" + name + "'";
db.Database.ExecuteSqlRaw(sql);
// GOOD — EF Core LINQ (always parameterized)
var users = await db.Users.Where(u => u.Name == name).ToListAsync();
// GOOD — raw SQL, safe interpolated form
db.Orders.FromSqlInterpolated($"EXEC sp_GetOrder {orderId}");No Unreviewed Destructive Migrations (block)
DropColumn, DropTable, and type-narrowing AlterColumn in a migration Up() must include a comment confirming data-loss impact has been reviewed and a rollback plan exists.
Tenant Filter at DbContext Level (see ADR-005)
Multi-tenant queries must use EF Core global query filters applied in OnModelCreating. Never add Where(x => x.TenantId == ...) manually in every handler.
No SELECT * in Application Queries
Select only the columns needed. SELECT * prevents covering index usage and breaks when columns are added or renamed.
Index FK Columns
All foreign key columns must have an index. HasIndex(o => o.CustomerId) in OnModelCreating.
Azure / Bicep
Managed Identity over Connection Strings (warn)
Authenticate to Azure services via Managed Identity (DefaultAzureCredential). Never embed connection strings or account keys in code or IaC. See ADR-001.
CAF Resource Naming
Resource names must follow CAF convention: <type>-<workload>-<env>-<region>-<instance>
Example: st-myapp-dev-eus-001 (storage account), kv-myapp-prod-weu-001 (key vault).
No allowBlobPublicAccess: true or Wide Firewall Rules (block)
Public blob access and 0.0.0.0–255.255.255.255 firewall rules are blocked. Use private endpoints or VNet-restricted rules.
Resource Locks on Production
All production resources must have a CanNotDelete lock. No exceptions without a documented justification in the PR.
Agent Routing (when using Claude Code with this plugin)
| Symptom | Agent |
| Frontend / browser issue | @angular-support |
| Backend / API exception | @dotnet-support |
| Database / query / migration | @sql-support |
| Infrastructure / deployment | @infra-support |
| Multi-layer / unknown layer | @fullstack-support (triage first) |
| PR review (multi-layer diff) | @fullstack-reviewer |
| Feature spec & planning | @fsp-analyst then /fsp-build |
| Architecture assessment | @fsp-architect |
See AGENTS.md at the repository root for the full routing table, cross-agent coordination rules, and MCP-first tool order.
Where files are headingNew Cursor rule files have more rules about planning and tracking tasks, and fewer about code style.
Of the Cursor rule files we read, the 3,978 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository3 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .codex/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

