|
| 1 | +# AGENTS.md — portal-web |
| 2 | + |
| 3 | +ASP.NET Core 9 web application — the XtremeIdiots Portal front-end. Razor views (runtime compile in Debug, build-time precompile in Release), SCSS via npm, Application Insights, Azure App Configuration, EF Core for identity / data-protection, and typed API clients for the Portal Repository, Servers Integration, and GeoLocation APIs. |
| 4 | + |
| 5 | +This file is the brief for the **GitHub Copilot coding agent** (and any other agent that follows the [agents.md](https://agents.md) convention) when it runs in a cloud runner without the local VS Code multi-root workspace context. |
| 6 | + |
| 7 | +> If you are a human reading this in VS Code, prefer `.github/copilot-instructions.md` for project orientation. `AGENTS.md` is the agent execution brief. |
| 8 | +
|
| 9 | +--- |
| 10 | + |
| 11 | +## Required reading (read these BEFORE doing any work) |
| 12 | + |
| 13 | +The `copilot-setup-steps.yml` workflow checks out `frasermolyneux/.github-copilot` at `./.github-copilot/` in the runner, so the paths below resolve. |
| 14 | + |
| 15 | +1. `.github/copilot-instructions.md` — repo-specific orientation, build commands, conventions |
| 16 | +2. `.github-copilot/.github/instructions/personal.working-preferences.instructions.md` |
| 17 | +3. `.github-copilot/.github/copilot-instructions.md` — org-wide catalog |
| 18 | +4. Stack-specific files — see **Stack guardrails** below |
| 19 | +5. `docs/ui-standards-guide.md` — **mandatory for any Razor view change** (buttons, icons, forms, destructive operations, legacy patterns to avoid) |
| 20 | +6. `docs/authorization-model.md` — how roles, policies, and `PotentialAccessProbe` work |
| 21 | +7. `docs/css-architecture-guide.md` — SCSS structure, tokens, components |
| 22 | +8. `docs/DATATABLE-IMPLEMENTATION-GUIDE.md` — server-backed data table patterns |
| 23 | + |
| 24 | +--- |
| 25 | + |
| 26 | +## Stack guardrails |
| 27 | + |
| 28 | +### Tenant facts (always-on) |
| 29 | +- `tenant.subscriptions`, `tenant.regions`, `tenant.identity`, `tenant.dns` |
| 30 | + |
| 31 | +### Enforceable standards |
| 32 | +- `standards.oidc-and-secrets` — **no client secrets** |
| 33 | +- `standards.dotnet-project` |
| 34 | +- `standards.azure-naming`, `standards.azure-tagging`, `standards.terraform-style` |
| 35 | +- `standards.branching-and-prs` |
| 36 | + |
| 37 | +### Patterns |
| 38 | +- `patterns.api-client` — consumes Portal Repository + Servers Integration + GeoLocation clients |
| 39 | +- `patterns.scss-build` — SCSS build pattern |
| 40 | +- `patterns.nbgv-versioning` |
| 41 | +- `patterns.terraform-remote-state` |
| 42 | + |
| 43 | +### Platform consumption contracts |
| 44 | +- `platform.workloads`, `platform.monitoring`, `platform.hosting`, `platform.connectivity` |
| 45 | + |
| 46 | +### Shared |
| 47 | +- `shared.api-client-abstractions` |
| 48 | +- `shared.observability-appinsights` |
| 49 | +- `shared.portal-core` — App Insights / ASP / SQL consumed from `portal-core` |
| 50 | + |
| 51 | +--- |
| 52 | + |
| 53 | +## Build, test, format |
| 54 | + |
| 55 | +```pwsh |
| 56 | +# .NET |
| 57 | +dotnet build src/XtremeIdiots.Portal.Web/XtremeIdiots.Portal.Web.csproj |
| 58 | +dotnet test src --filter "FullyQualifiedName!~IntegrationTests" |
| 59 | +dotnet format src/XtremeIdiots.Portal.Web.sln --verify-no-changes |
| 60 | +
|
| 61 | +# SCSS (npm install runs automatically on first build via MSBuild target) |
| 62 | +cd src/XtremeIdiots.Portal.Web |
| 63 | +npm install |
| 64 | +npm run build:css:dev |
| 65 | +cd ../.. |
| 66 | +
|
| 67 | +# Terraform |
| 68 | +terraform -chdir=terraform fmt -check -recursive |
| 69 | +terraform -chdir=terraform init -backend-config=backends/dev.backend.hcl |
| 70 | +terraform -chdir=terraform validate |
| 71 | +terraform -chdir=terraform plan -var-file=tfvars/dev.tfvars |
| 72 | +``` |
| 73 | + |
| 74 | +Release builds treat warnings as errors and precompile Razor views — check `ValidateRazor=true` Razor compilation succeeds before declaring done. |
| 75 | + |
| 76 | +--- |
| 77 | + |
| 78 | +## Do NOT |
| 79 | + |
| 80 | +- ❌ Do not `git commit`, `git push`, force-push, rebase, or branch-mutate. Work on the assigned branch only. |
| 81 | +- ❌ Do not introduce client secrets. App Configuration + Key Vault + managed identity only. |
| 82 | +- ❌ Do not bypass `dotnet format`, `dotnet test`, `terraform fmt`, `terraform validate`, or the SCSS build. |
| 83 | +- ❌ Do not use legacy Razor / Bootstrap classes: `control-label`, `help-block`, `float-e-margins`, `btn-xs`, `dl-horizontal`, `admin-actions-filters`, `fa-save`, `fa-edit`, `type="button"` on `<a>` tags. See `docs/ui-standards-guide.md`. |
| 84 | +- ❌ Do not use inline `onclick` / `onsubmit` confirm handlers — use Tier 1 (confirmation page) or Tier 2 (`data-confirm` attribute) per the UI standards guide. |
| 85 | +- ❌ Do not use `ClaimedGamesAndItems` or direct claim checks as authorization gates — use `PotentialAccessProbe` instead. The handler is the single source of truth. |
| 86 | +- ❌ Do not bypass the `{Domain}.{Action}` policy convention — register new policies via `PolicyExtensions.AddXtremeIdiotsPolicies()`. |
| 87 | +- ❌ Do not modify `.github/workflows/`, `.github/dependabot.yml`, or `version.json` unless that is the explicit task. |
| 88 | + |
| 89 | +--- |
| 90 | + |
| 91 | +## Validation before opening PR |
| 92 | + |
| 93 | +- [ ] `dotnet build` succeeds (clean) — Release config catches warning-as-error and Razor precompile issues |
| 94 | +- [ ] `dotnet test --filter "FullyQualifiedName!~IntegrationTests"` passes |
| 95 | +- [ ] `dotnet format --verify-no-changes` passes |
| 96 | +- [ ] `npm run build:css:dev` succeeds |
| 97 | +- [ ] `terraform fmt -check -recursive` passes |
| 98 | +- [ ] `terraform validate` + `terraform plan -var-file=tfvars/dev.tfvars` succeed |
| 99 | +- [ ] All Razor view changes follow `docs/ui-standards-guide.md` (buttons, icons, forms, destructive gating) |
| 100 | +- [ ] New authorization checks use `PotentialAccessProbe` for "can user potentially..." gates |
| 101 | +- [ ] No new secrets / GUIDs / connection strings |
| 102 | +- [ ] PR body cites each acceptance criterion |
| 103 | +- [ ] Risk/rollout section filled in |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## Escalation |
| 108 | + |
| 109 | +If you hit any of the conditions below, **open the PR as draft** and **apply the `needs-decision` label** instead of pushing forward to ready-for-review. Post a comment on the originating issue summarising what's blocking you and what decision is needed. |
| 110 | + |
| 111 | +Stop and escalate when: |
| 112 | + |
| 113 | +- The change requires modifying `AdditionalPermission` constants in the `portal-repository` abstractions package (coordinate there first). |
| 114 | +- A new authorization policy crosses domain boundaries and would need cross-repo coordination. |
| 115 | +- A `code-review` finding is **High** and cannot be resolved in-scope. |
| 116 | +- The SCSS build fails and `npm install` + `npm run build:css:dev` does not resolve it. |
0 commit comments