-
Notifications
You must be signed in to change notification settings - Fork 1
Contributing
This is the long-form contributor guide. The short version lives in CONTRIBUTING.md.
These constraints are not negotiable in casual PRs — changing any of them needs a discussion in an issue first.
- No backend. Every privileged call goes from the browser directly to Microsoft Graph or Azure Resource Manager.
-
No bundler, no framework.
Portal/is plain HTML / CSS / vanilla JavaScript so it can be served by any static host with no build step. -
No new third-party origins without a corresponding update to the Content Security Policy in
Portal/staticwebapp.config.json. The CSP is the security boundary — keep it minimal. -
No inline scripts and no
eval. The CSP forbids both. -
Tokens stay in
sessionStorage. Do not introduce code that persists access tokens, refresh tokens, or claims tolocalStorage, IndexedDB, cookies, or any other persistent store. - Delegated permissions only. No app-only permissions, no client secrets, no service principal credentials anywhere in the codebase or deployment artifacts.
Read How It Works before making non-trivial changes. The sections most likely to surprise contributors:
-
auth.jsowns claims-threading. A new API code path that calls Microsoft Graph or ARM directly (instead of going through the existing clients) will skip claims threading and fail mid-operation when policies require auth contexts. -
api/batch-client.jsowns concurrency. Don'tPromise.allan unbounded number of ARM calls — use the existing concurrency primitive. -
api/graph-client.jsowns batch chunking and429retry. New Graph calls should go through it. -
policy-cache.jsis in-memory and tenant-keyed. Adding a new fetch path should reuse it rather than re-fetching policies. -
roles.jsis the rendering brain. Changes that touch role state should respect the stableuidkeying so selection survives refreshes.
- Modern JavaScript (ES2022+), no transpilation step.
- Two-space indentation, single quotes, semicolons.
- Small, well-named functions; comments where intent is non-obvious.
- DOM updates batched where reasonable; no animation frame thrashing.
- Public surface (anything attached to
window) stays small and stable. - Prefer
const; reach forletonly when you reassign; avoidvar.
For any user-facing change, test at minimum:
- Latest Microsoft Edge (Chromium) on Windows
- Latest Mozilla Firefox on Windows
- Latest Safari on macOS or iOS
When testing across tenants, cover at least:
- A single-tenant scenario (you are signed in to your home tenant only)
- A multi-tenant scenario (you have eligibilities in your home tenant and as a guest in another)
If your change involves a new third-party origin (a new CDN, a new API), update Portal/staticwebapp.config.json in the same PR and call it out at the top of the PR description. PRs that load resources from origins not listed in the CSP will fail in production with cryptic errors — saving reviewers the deciphering work is appreciated.
Before opening a PR, confirm:
- No backend, proxy, or third-party API was added.
- No new third-party origin was introduced without a corresponding CSP update.
- No inline scripts and no
evalwere introduced. - Tokens still live only in
sessionStorage. - Delegated permissions only — no app permissions, secrets, or service-principal credentials added.
- Tested in Chromium and Firefox (Safari for UI changes).
- If UI changed, screenshots or a short GIF are attached.
- If Bicep was changed,
Portal/deploy/azuredeploy.jsonwas rebuilt. -
CHANGELOG.mdupdated under## [Unreleased]for any user-visible change.
The PR template enforces most of this — you'll see the checklist auto-populated when you open the PR.
Conventional Commits style is encouraged but not strictly required:
feat(profiles): support tenant-scoped imports
fix(batch-client): honor Retry-After in seconds vs HTTP-date
docs(readme): clarify managed vs self-hosted authority
The Bicep file Portal/deploy/bicep/portal-selfhosted.bicep is the source of truth. The corresponding ARM template Portal/deploy/azuredeploy.json is regenerated by the Sync Deployment Templates workflow. PRs that change Bicep without updating the ARM artifact are auto-flagged. To regenerate locally:
az bicep build --file Portal/deploy/bicep/portal-selfhosted.bicep --outfile Portal/deploy/azuredeploy.jsonThis project embraces AI-assisted development. If you used tools like GitHub Copilot, Claude, or ChatGPT for substantial portions of your contribution, please mention it in the PR description and which areas you used them on. All code must be understood, tested, and validated regardless of how it was produced.
- Bugs: bug report template
- Features: feature request template
- Documentation: documentation issue template
- Questions and ideas: GitHub Discussions
By contributing, you agree your contributions will be licensed under the MIT License that covers this project.
Thank you for helping make the portal better.