Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
225 commits
Select commit Hold shift + click to select a range
2aebe5c
feat: add bulk license pricing import/export
TechSG-Martin Sep 25, 2026
44210a4
feat(standards): add Teams files policy standard
kris6673 Sep 28, 2026
5c7b583
chore(openapi): regenerate API spec
github-actions[bot] Oct 2, 2026
9f48ab3
docs: 11.0.2
bmsimp Oct 2, 2026
9928d34
feat(templatelib): add delete library action with permission check
rvdwegen Oct 3, 2026
aea5642
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
rvdwegen Oct 3, 2026
4fdab60
perf(graph): cut per-call table reads and pipeline churn in request h…
Zacgoose Oct 2, 2026
b46c2a4
perf(intune): index policy results and fetch device statuses per batch
Zacgoose Oct 2, 2026
daaa6b2
perf(identity): stream MFA state rows into the cache writer
Zacgoose Oct 2, 2026
8e26dc5
perf(core): return text without tokens before any replacement lookups
Zacgoose Oct 2, 2026
1ff3cef
perf(cache): add per-row note properties without the Add-Member pipeline
Zacgoose Oct 2, 2026
9273e8f
perf(cache): drop per-row pipelines in the Teams Voice and SMTP AUTH …
Zacgoose Oct 2, 2026
2c115c6
fix(tables): open AllTenants row links scoped to the row's tenant
Zacgoose Oct 5, 2026
bc3887b
fix(baselines): resolve variables in group template names before matc…
Zacgoose Oct 5, 2026
d2bbc74
fix(mfa): surface the Entra error when the MFA connector token fails
Zacgoose Oct 5, 2026
00b87af
fix(sharepoint): edit and unlock locked and classic sites from Edit Site
Zacgoose Oct 5, 2026
8f43b4d
chore(deps): update AzBobbyTables to 3.8.2
Zacgoose Oct 5, 2026
bf62099
fix(alerts): keep storage quota alert snoozes matching across runs
Zacgoose Oct 5, 2026
95a5f10
fix(sharepoint): apply the version policy to existing libraries and s…
Zacgoose Oct 5, 2026
d32bfc3
fix to use exclusions etc
KelvinTegelaar Oct 5, 2026
76bddae
Merge pull request #732 from TechSG-Martin/feat/license-pricing-csv
KelvinTegelaar Oct 5, 2026
4509626
sorts buttons correct
KelvinTegelaar Oct 5, 2026
b52e13e
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
KelvinTegelaar Oct 5, 2026
ce802af
fix(tests): run each tenant's test suites sequentially to avoid parsi…
Zacgoose Oct 5, 2026
9d3df8a
chore(build): cap dev container logs and prune dangling images on start
Zacgoose Oct 5, 2026
ee97bbc
Merge pull request #718 from CyberDrain/chore/openapi-spec-update-202…
KelvinTegelaar Oct 5, 2026
56d1692
tap enabled/disabled
KelvinTegelaar Oct 5, 2026
eb6a568
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
KelvinTegelaar Oct 5, 2026
c1c7059
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
Zacgoose Oct 5, 2026
5247f3f
Update openapi.json
Zacgoose Oct 5, 2026
b68d32b
feat(portals): add opt-in login_hint to portal links
NickVAg Oct 5, 2026
33519e3
shared mailbox baseline
KelvinTegelaar Oct 5, 2026
4ab7994
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
KelvinTegelaar Oct 5, 2026
ad13315
add group reviewer to baselines
KelvinTegelaar Oct 5, 2026
f35133c
chore(hudu): bump vendored HuduAPI module to 4.1.0.1
Zacgoose Oct 5, 2026
fa3e7b6
feat(scheduler): filter ListScheduledItems by task state and reference
renada-jacob Oct 5, 2026
b6e507f
fixes tests due to me breaking them.
KelvinTegelaar Oct 5, 2026
4be139b
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
KelvinTegelaar Oct 5, 2026
fcddffa
Merge pull request #825 from Renada-Solutions/feat/scheduled-items-re…
KelvinTegelaar Oct 5, 2026
64e6da8
feat(vacation): add tenant vacation defaults & usageLocation default
JohnDuprey Oct 5, 2026
54c7e3c
fix(community-repos): refuse adds GitHub cannot resolve and clear gho…
JohnDuprey Oct 5, 2026
7193b4f
fix(halo): key consolidated tickets on the task, not the title
JohnDuprey Oct 5, 2026
d9f2543
feat(autopilot): assign profiles to groups with exclusions, grade ass…
JohnDuprey Oct 6, 2026
e1645e1
chore(deps): bump react-is from 19.2.8 to 19.3.0 in /frontend
dependabot[bot] Oct 6, 2026
afc0b9f
chore(deps-dev): bump @storybook/addon-docs in /frontend
dependabot[bot] Oct 6, 2026
8f01f4e
chore(deps): bump swagger-ui-dist from 5.32.12 to 5.33.1 in /frontend
dependabot[bot] Oct 6, 2026
80ec260
chore(deps-dev): bump eslint-config-next in /frontend
dependabot[bot] Oct 6, 2026
f87cf37
chore(deps): bump monaco-editor from 0.55.1 to 0.57.0 in /frontend
dependabot[bot] Oct 6, 2026
da38eaf
chore(docs): refresh published docs page snapshot
github-actions[bot] Oct 6, 2026
4bcdc6d
feat(orchestrator): skip overlapping recurring runs and pass run mode…
Zacgoose Oct 6, 2026
ffff932
fix(ninjaone): name queued NinjaOne tasks after their tenant
Zacgoose Oct 6, 2026
798d010
feat(tools): add MCP OAuth flow test harness
Zacgoose Oct 6, 2026
d561690
fix(mcp): run signed-in MCP connectors on the user's role only
Zacgoose Oct 6, 2026
874d033
feat(mcp): list only the tools the caller's roles allow
Zacgoose Oct 6, 2026
d5e7b00
Merge pull request #835 from CyberDrain/dependabot/npm_and_yarn/front…
KelvinTegelaar Oct 6, 2026
b6af730
Merge pull request #834 from CyberDrain/dependabot/npm_and_yarn/front…
KelvinTegelaar Oct 6, 2026
1d810f8
Merge pull request #833 from CyberDrain/dependabot/npm_and_yarn/front…
KelvinTegelaar Oct 6, 2026
bbed5d3
Merge pull request #832 from CyberDrain/dependabot/npm_and_yarn/front…
KelvinTegelaar Oct 6, 2026
c585659
Merge pull request #831 from CyberDrain/dependabot/npm_and_yarn/front…
KelvinTegelaar Oct 6, 2026
835c630
Merge pull request #817 from CyberDrain/chore/docs-published-pages-up…
KelvinTegelaar Oct 6, 2026
7bee3bf
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
Zacgoose Oct 6, 2026
1ba2766
test(auth): pin built-in and custom role permissions and their access…
Zacgoose Oct 6, 2026
134c23c
feat(baselines): add Azure MFA push apps baseline
Zacgoose Oct 6, 2026
4ecdfe8
Update CIPP-Standard-Agent.md
Zacgoose Oct 6, 2026
df77813
fix(alerts): skip logging Defender alerts when Lighthouse is unavailable
Zacgoose Oct 6, 2026
f1538eb
perf(tests): run each tenant's suites one at a time without pinning a…
Zacgoose Oct 6, 2026
72b5246
perf(tests): drop per-user pipelines from ZTNA21811 and Copilot readi…
Zacgoose Oct 6, 2026
4f17b8c
fix(mfa): give the MFA connector its own app management exemption
Zacgoose Oct 6, 2026
47033d1
refactor(teams-share): move reports into a Reports folder
Zacgoose Oct 6, 2026
aa5649c
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into feat/te…
kris6673 Oct 6, 2026
5b049aa
feat(hudu): per-tenant opt-out of LAPS and BitLocker sync
JohnDuprey Oct 6, 2026
ad93bda
feat(users): surname prefix and core tokens for username formats
JohnDuprey Oct 6, 2026
003320b
feat(jit): notify on JIT admin creation, not only on expiry
JohnDuprey Oct 6, 2026
bdbb91e
fix(tenant-selector): sort favourite tenants alphabetically
JohnDuprey Oct 6, 2026
e4517a4
feat(vacation): add users to groups for the vacation period
JohnDuprey Oct 6, 2026
ec9e518
refactor(hudu): build device hash material without +=
Zacgoose Oct 6, 2026
449ab5b
fix(baselines): count license-skipped standards as aligned for stage …
JohnDuprey Oct 6, 2026
e12f9d5
feat(transport): template mode on the rule editor; variables resolve …
JohnDuprey Oct 6, 2026
937c568
feat: show open Microsoft service health issues on the dashboard
kris6673 Oct 7, 2026
6c942d0
feat(exchange): add support for custom mailbox attributes management
rvdwegen Oct 7, 2026
d9f49ce
Merge pull request #846 from kris6673/feat/dashboard-service-health
KelvinTegelaar Oct 7, 2026
d80c34b
Merge pull request #822 from NickVAg/feat/add-login-hint
KelvinTegelaar Oct 7, 2026
a6c7d74
fixes login hint issue
KelvinTegelaar Oct 7, 2026
a04bd52
Update openapi.json
Zacgoose Oct 7, 2026
a1566ae
fix(identity): show directory role SID on the Roles page
Zacgoose Oct 7, 2026
3fbffca
feat(variables): add %globaladminsid% and %deviceadminsid% reserved v…
Zacgoose Oct 7, 2026
b126684
Update openapi.json
Zacgoose Oct 7, 2026
e50ee7d
add use report db
KelvinTegelaar Oct 7, 2026
86a8ffc
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
KelvinTegelaar Oct 7, 2026
1f7e205
refactor(exchange): qualify regex options
Zacgoose Oct 7, 2026
0f501d3
fixes "Set guest access to expire automatically" fails to set days un…
KelvinTegelaar Oct 7, 2026
d9ba338
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
KelvinTegelaar Oct 7, 2026
5974f3a
allow moving of stages
KelvinTegelaar Oct 7, 2026
e5ae7b9
new ondrive alert
KelvinTegelaar Oct 7, 2026
88c1bf2
chore: move baselines into its own module
Zacgoose Oct 7, 2026
53f4030
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
Zacgoose Oct 7, 2026
5e1d972
fix(baselines): store baseline result JSON columns as plain strings
Zacgoose Oct 7, 2026
adb2b25
fix(scheduler): allow CIPPBaselines commands in scheduled tasks
Zacgoose Oct 7, 2026
29dc394
perf(scheduler): validate commands without importing sibling modules
Zacgoose Oct 7, 2026
bc7743e
perf(tests): run test refreshes on the background workers
Zacgoose Oct 7, 2026
9eebd9f
chore(openapi): type baseline storage fields
Zacgoose Oct 7, 2026
6b6d725
refactor(http): log API access once in the dispatcher
Zacgoose Oct 7, 2026
880ff5a
Update openapi.json
Zacgoose Oct 7, 2026
3f03345
standard items
KelvinTegelaar Oct 7, 2026
2099eb5
fix(standards): read the Teams protection policy without a fixed name
Zacgoose Oct 7, 2026
4be9ea3
feat(realtime): live queue and job progress over Craft SSE
Zacgoose Oct 8, 2026
26d7da7
feat(identity): add approval flow for JIT admin requests
Zacgoose Oct 8, 2026
134952a
fix(identity): return 404 from ListUserPhoto when the user has no photo
Zacgoose Oct 8, 2026
e0a8700
Update openapi.json
Zacgoose Oct 8, 2026
4e3ee94
Update openapi.json
Zacgoose Oct 8, 2026
a3e337e
fix(ui): format end date columns as dates
Zacgoose Oct 8, 2026
0b14d79
refactor(identity): group JIT Admin pages into a tabbed layout
Zacgoose Oct 8, 2026
274545e
fix(table): size date columns with the same date check the formatter …
Zacgoose Oct 8, 2026
665357a
fix(identity): key the JIT Admin requests table on the selected tenant
Zacgoose Oct 8, 2026
2423301
fix(identity): send JIT Admin approval push notifications on CIPP-NG …
Zacgoose Oct 8, 2026
89220c3
fix(ui): refer to the new CIPP infrastructure instead of CIPP-NG
Zacgoose Oct 8, 2026
df5b8c5
docs(identity): document JIT Admin approval
Zacgoose Oct 8, 2026
7ad8161
chore(docs): refresh published docs page snapshot
github-actions[bot] Oct 8, 2026
3822d8b
Merge pull request #856 from CyberDrain/chore/docs-published-pages-up…
Zacgoose Oct 8, 2026
77aed40
fixes bug with encrypted values
KelvinTegelaar Oct 8, 2026
38ee62d
updated appdeploy
KelvinTegelaar Oct 8, 2026
799c478
add sort
KelvinTegelaar Oct 8, 2026
cdb604d
add group ownership removal
KelvinTegelaar Oct 8, 2026
61072cf
feat(build): persist dev azurite tables as one paged file per table
Zacgoose Oct 8, 2026
24f3317
Update azurite-table-partition.js
Zacgoose Oct 8, 2026
c57dd0a
feat(http): pace Graph and EXO calls per tenant across all workers
Zacgoose Oct 8, 2026
467daf3
perf(tests): share security simulation work across a suite run
Zacgoose Oct 8, 2026
8f35327
fix(baselines): stop re-collecting cache types that are collected but…
Zacgoose Oct 8, 2026
1c71d37
perf(baselines): list the definition folder once per worker
Zacgoose Oct 8, 2026
a518027
fix(tests): score security simulations against what each control real…
Zacgoose Oct 8, 2026
bc8f7e2
fix(tests): grade security simulations against secure values the scen…
Zacgoose Oct 8, 2026
d4d4a72
perf(tests): grade each security simulation standard once
Zacgoose Oct 8, 2026
9e3a6fd
fix(dbcache): read SharePoint tenant settings with certificate auth
Zacgoose Oct 8, 2026
85c3ace
fix(templates): hash standards templates containing scalar arrays or …
Zacgoose Oct 8, 2026
2f6a58e
fix: match superadmin role alert exactly not lazily
Zacgoose Oct 8, 2026
76eb01f
fix(standards): grade every MOERA domain for DMARC and alert only on …
Zacgoose Oct 8, 2026
3d427f9
fix(applications): wait for a new service principal before granting p…
Zacgoose Oct 8, 2026
cbb0c5c
feat(baselines): add mailbox default audit set standard
Zacgoose Oct 8, 2026
a90a8e3
feat(pwpush): Add first party CIPPPwPush module
JohnDuprey Oct 8, 2026
7202618
test: fix locale-dependent signing cert expiry and stale Hudu credent…
Zacgoose Oct 9, 2026
02b7283
fix(conditional): move authentication flows out of the P2 risk section
Zacgoose Oct 9, 2026
d0801e2
fix(conditional): allow selecting multiple authentication flow transf…
Zacgoose Oct 9, 2026
52b3378
fix(conditional): save authentication flow transfer methods in Graph …
Zacgoose Oct 9, 2026
7f1d28a
test(tests): cover combined authentication flow transfer methods in C…
Zacgoose Oct 9, 2026
d797978
fix(baselines): disable and delete accounts with delegated permissions
Zacgoose Oct 9, 2026
488c7d8
fix(tests): read CIS 4.1 from Intune device management settings
Zacgoose Oct 9, 2026
1396fa2
fix(tests): check published label policies for CIS 3.3.1
Zacgoose Oct 9, 2026
0a2bdde
fix(tests): normalise numeric SharePoint sharing enums in CIS 7.2.3, …
Zacgoose Oct 9, 2026
2c46801
fix(licenses): accept decimal prices in the optimization page price o…
Zacgoose Oct 9, 2026
e610b44
fix(cache): report a skipped duplicate cache run instead of claiming …
Zacgoose Oct 9, 2026
6fd8147
fix(standards): report a skipped duplicate standards run instead of c…
Zacgoose Oct 9, 2026
d46dbbb
ci(baselines): generate a combined baseline standards JSON for standa…
Zacgoose Oct 9, 2026
9647439
test(offboarding): keep offboarding options in sync across the valida…
Zacgoose Oct 9, 2026
b469536
ci(baselines): also check the combined baseline JSON on PRs to main
Zacgoose Oct 9, 2026
a1dc5bf
fix(baselines): update a transport rule the cache missed instead of f…
Zacgoose Oct 9, 2026
07e9ca7
fix(identity): save JIT admin settings without a maximum duration aft…
Zacgoose Oct 9, 2026
445e7ca
fix(api): return an error status when an endpoint's catch block fails
Zacgoose Oct 9, 2026
b9828e2
Update openapi.json
Zacgoose Oct 9, 2026
aac78d9
token fix
KelvinTegelaar Oct 9, 2026
df8ed8c
Update appsettings.Production.json
Zacgoose Oct 9, 2026
95f7002
fix(baselines): remove license gate on authentication methods
JohnDuprey Oct 9, 2026
0f78cdf
fix: add back in empty array
JohnDuprey Oct 9, 2026
4fc9e4e
fix(api): return 500 instead of 403/400 when an upstream call fails
Zacgoose Oct 9, 2026
dea8ca0
Update openapi.json
Zacgoose Oct 9, 2026
50ef81f
fix(api): continue bulk actions past a failed row and stop retrying 4…
Zacgoose Oct 9, 2026
6f69e90
fix(api): return accurate status codes from endpoint error paths
Zacgoose Oct 9, 2026
b6485a4
Update openapi.json
Zacgoose Oct 9, 2026
06840a5
fix(api): let helpers signal input, not-found and per-item failures s…
Zacgoose Oct 9, 2026
d18a885
Update openapi.json
Zacgoose Oct 9, 2026
67a6838
Update Get-GradientToken.ps1
Zacgoose Oct 9, 2026
58c7a0f
docs(api): document endpoint status codes and error-signalling helpers
Zacgoose Oct 9, 2026
b75ddaf
feat(msp-apps): add NinjaOne to MSP vendor apps
Zacgoose Oct 9, 2026
75cc35d
feat(branding): add option to turn off the cover image fade
Zacgoose Oct 9, 2026
650c99f
Update openapi.json
Zacgoose Oct 9, 2026
3664b63
feat(halo): background auto-map with tenant ID and exact name matching
Zacgoose Oct 9, 2026
4087420
feat(hudu): auto-map tenants via HaloPSA client and exact company name
Zacgoose Oct 9, 2026
218fe28
chore(build): add memory-optimised Premium SKU profiles and scale Pre…
Zacgoose Oct 9, 2026
5bd8596
feat(conditional): add list custom variables for CA templates
Zacgoose Oct 10, 2026
6bdabbd
new GSA deployment standard
KelvinTegelaar Oct 10, 2026
681b376
Merge pull request #742 from kris6673/feat/teams-files-policy
KelvinTegelaar Oct 10, 2026
30d4791
feat(baselines): manage external meeting bots in the Teams meeting po…
JohnDuprey Oct 10, 2026
bba5201
feat(onedrive): allow a custom name when adding a OneDrive shortcut
JohnDuprey Oct 10, 2026
21e16da
feat(mailboxes): warn when a converted shared mailbox still needs a l…
JohnDuprey Oct 10, 2026
f941655
fix(build): rebuild Loki indexes after loading paged azurite tables
JohnDuprey Oct 10, 2026
18ac3bc
new standards for CIS foundation
KelvinTegelaar Oct 10, 2026
40cb269
Merge branch 'dev' of https://github.com/CyberDrain/CIPP into dev
KelvinTegelaar Oct 10, 2026
0bcaab6
feat(bec): look back 30 days for tenants with Entra ID P1 or P2
JohnDuprey Oct 10, 2026
5d27fd1
fix(exchange): fall back to Get-MessageTraceV2 for GCC message traces
JohnDuprey Oct 10, 2026
e4d1f73
new baselines for EISCDA
KelvinTegelaar Oct 10, 2026
6b75a21
feat(intune): author settings catalog templates and validate template…
Zacgoose Oct 10, 2026
3af3e76
Update openapi.json
Zacgoose Oct 10, 2026
64d65a7
perf(tenants): filter Get-Tenants with a literal script block
Zacgoose Oct 10, 2026
2bb59f8
perf(tests): cut allocation and exceptions in the tests run and cache…
Zacgoose Oct 11, 2026
7089e34
docs(agents): add compliance test and backend alert guides and PowerS…
Zacgoose Oct 11, 2026
bdb48df
perf(graph): parse response bytes directly and drop per-call table re…
Zacgoose Oct 11, 2026
7f95503
perf(cache): sample row shapes in CIPPSharp and cut parse and seriali…
Zacgoose Oct 11, 2026
515cc97
perf(cache): remove exception-throwing lookups from cache collectors
Zacgoose Oct 11, 2026
46b217f
perf(cache): default Copilot reports to D28 and remove remaining exce…
Zacgoose Oct 11, 2026
bff3d9b
chore(config): capture PowerShell verbose and debug output in dev con…
Zacgoose Oct 11, 2026
9683d00
Update openapi.json
Zacgoose Oct 11, 2026
289ebab
perf(tests): cut exception churn and cache size in the tests run
Zacgoose Oct 11, 2026
be1ae8e
perf(tables): reuse table clients across AzBobbyTables calls
Zacgoose Oct 11, 2026
8a1ece0
perf(baselines): look up engine commands directly and cut exception c…
Zacgoose Oct 11, 2026
4acadde
perf(config): load the tests, baselines, cache and alerts modules int…
Zacgoose Oct 11, 2026
2ddfefb
feat(baselines): filter the fleet overview by baseline and stage
JohnDuprey Oct 11, 2026
9015dcd
fix(baselines): emit non-package standards from the stage helper
JohnDuprey Oct 11, 2026
b518be7
feat(identity): scope JIT admin approval to tenants and tenant groups
kris6673 Oct 11, 2026
52a8a9d
feat(baselines): FIDO2 passkey profile guidance, Microsoft passkey op…
Zacgoose Oct 12, 2026
38af20a
Update baselineStandards.json
Zacgoose Oct 12, 2026
4749ec9
fix(baselines): stop the unsaved-changes prompt when saving a new bas…
Zacgoose Oct 12, 2026
1280c64
Merge pull request #876 from kris6673/feat/jit-approval-tenant-scope
Zacgoose Oct 12, 2026
92aba2f
feat(ninjaone): auto-map tenants from the extension timer in a single…
Zacgoose Oct 12, 2026
78107ca
fix(ninjaone): limit timer auto-map to name matches and document auto…
Zacgoose Oct 12, 2026
6d5e904
Fix push notification permission handling
Zacgoose Oct 12, 2026
138ede1
fix(sharepoint): return one quota row per tenant for AllTenants
Zacgoose Oct 12, 2026
e0b109a
feat(sharepoint): show per-tenant storage table on AllTenants
Zacgoose Oct 12, 2026
ce37e80
mime encoding words and long names fixes
KelvinTegelaar Oct 12, 2026
e45ac9f
perf(auditlog): cut directory loads and per-record cost in the rules …
Zacgoose Oct 12, 2026
e207433
perf(auditlog): expand rule exclusions only for rules that cover the …
Zacgoose Oct 12, 2026
8f01e51
fix(alerts): filter audit-log coverage ledger server-side
JohnDuprey Oct 12, 2026
1cfccdb
chore: bump version to 11.1.0
JohnDuprey Oct 12, 2026
2369c0d
fix(intune): use flex gap on wrapping settings catalog stacks
Zacgoose Oct 12, 2026
80b0bd1
test(identity): add default table mock for Pester 6 in JIT approval n…
Zacgoose Oct 12, 2026
7b95bb6
docs(flags): update Baselines flag description wording
JohnDuprey Oct 12, 2026
a2cb181
chore(frontend): bump sharp, prosemirror-view, source-map-js
JohnDuprey Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
100 changes: 73 additions & 27 deletions .github/agents/CIPP-Alert-Agent.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,91 @@
---
name: CIPP Frontend Alert Registrar
name: CIPP Alert Builder
description: >
Adds new alert entries to src/data/alerts.json in the CIPP frontend.
The agent must never modify any other file or perform any other change.
Adds or changes scripted alerts in backend/Modules/CIPPAlerts (Get-CIPPAlert<Name>.ps1): per-tenant checks that
report what they find through Write-AlertTrace. The frontend entry is a separate job for CIPP-Frontend-Alert-Agent.md.
---

# CIPP Frontend Alert Registrar
# CIPP Alert Builder

## Mission

You are a **frontend alert registrar** responsible for updating the `src/data/alerts.json` file to include new alerts.
Write or change an alert so that it:

Your role is **strictly limited** to adding a new JSON entry describing the alert’s metadata.
You do not touch or inspect any other part of the codebase.
- reports everything it finds for one tenant in a single `Write-AlertTrace` call, including an empty result,
- never reports "clear" when it could not check,
- costs time and memory in proportion to the tenant. Alerts run on a schedule for every tenant, and tenants with 50k
users or 20k mailboxes are normal.

---

## Scope of Work
## Anatomy

This agent is used when a new alert must be surfaced to the frontend — for example, after a new backend `Get-CIPPAlert*.ps1` alert has been added.
```powershell
function Get-CIPPAlertThing {
<#
.FUNCTIONALITY
Entrypoint
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[Alias('input')]
$InputValue,
$TenantFilter
)

Tasks include:
try {
$Users = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?$select=id,userPrincipalName,accountEnabled' -tenantid $TenantFilter
$AlertData = foreach ($User in $Users) {
if ($User.accountEnabled) { continue }
[PSCustomObject]@{
UserPrincipalName = $User.userPrincipalName
Id = $User.id
Message = 'User {0} is disabled' -f $User.userPrincipalName
Tenant = $TenantFilter
}
}
Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $AlertData
} catch {
$ErrorMessage = Get-CippException -Exception $_
Write-LogMessage -API 'Alerts' -tenant $TenantFilter -message "Failed to check things for $($TenantFilter): $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage
}
}
```

- Opening `src/data/alerts.json`
- Appending one new JSON object describing the new alert
- Preserving JSON structure, indentation, and trailing commas exactly as in the existing file
- Validating that the resulting JSON is syntactically correct
- File: `CIPPAlerts/Public/Alerts/Get-CIPPAlert<Name>.ps1`. It also needs an entry in `frontend/src/data/alerts.json`
(`CIPP-Frontend-Alert-Agent.md`) to be selectable in the UI; `inputName` there is the property read from `$InputValue`.
- `$InputValue` is the alert's configuration: a scalar for single-input alerts, an object for multi-input ones. Keep
reading the legacy scalar form when you add fields.

---

## Alert Format
## Reporting

Each alert entry in `src/data/alerts.json` is a JSON object with the following structure:
- **Call `Write-AlertTrace` once per run with the full result**, also when it is empty: an empty run resolves whatever
was still open. Use `-Append` only for event-stream alerts that see a slice, not the whole picture.
- **Do not call it when the check failed part-way.** "Could not check" is not "clear"; it would resolve open alerts.
Log the failure instead.
- **Items need a stable identity.** `Get-AlertContentHash` keys an item on `UserPrincipalName`, then `Id`, then
`Message`, and otherwise on the whole item. Include one of those, so a changing value (a day count, a timestamp) does
not turn the same finding into a new alert on every run.
- Only New and Reopened items notify; snoozes are handled for you.

```json
{
"name": "<alertName>",
"label": "A nice label for the alert",
"requiresInput": true,
"inputType": "switch",
"inputLabel": "Exclude disabled users?",
"inputName": "InactiveLicensedUsersExcludeDisabled",
"recommendedRunInterval": "1d"
}
```
---

## Data and performance

- Prefer the cache when it holds what you need (`New-CIPPDbRequest -TenantFilter $TenantFilter -Type '<Type>'`, with a
field list when you read a few fields); call Graph or Exchange live only for data that must be current.
- `$select` only the fields you read, and filter server-side when Graph supports it.
- Follow the hot-path rules in `.github/copilot-instructions.md`. For alerts that means above all: no
`New-GraphGetRequest ... | Where-Object` over a whole user or mailbox list (a `foreach` with `if`/`continue`), and no
scan of one list inside a loop over another (build a hashtable keyed on the join field first).

---

## Tests

- `backend/Tests/Alerts/`: stub the Graph/cache reads and `Write-AlertTrace`, then assert the items passed to
`-data`, an empty run, and that a failed read does not call `Write-AlertTrace`.
- Load `Shared/CIPPSharp/bin/CIPPSharp.dll` in `BeforeAll` when the alert uses a `[CIPP.*]` type.
160 changes: 160 additions & 0 deletions .github/agents/CIPP-Endpoint-Agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
name: CIPP HTTP Endpoint Builder
description: >
Adds or changes HTTP endpoints in backend/Modules/CIPPHTTP (Invoke-List/Add/Edit/Remove/Exec*) and the
CIPPCore helpers they call, with response shapes and status codes the frontend, MCP and the response cache
depend on.
---

# CIPP HTTP Endpoint Builder

## Mission

Write or change an HTTP endpoint so that it:

- returns the body shape the frontend expects,
- returns a status code that tells the truth about what happened,
- documents its request contract through code the OpenAPI generator can read.

Status codes are not cosmetic in CIPP:

- **Response cache:** the runtime caches 2xx GET responses (for up to 600 s). An error returned as 200 is cached and served as data.
- **MCP:** the MCP tool layer treats `>= 400` as an error and anything else as a result.
- **Frontend:** the frontend retries and renders based on the status.

---

## Anatomy

```powershell
function Invoke-ExecThing {
<#
.FUNCTIONALITY
Entrypoint
.ROLE
Identity.User.ReadWrite
.DESCRIPTION
Shown in the generated API docs.
#>
[CmdletBinding()]
param($Request, $TriggerMetadata)
$Headers = $Request.Headers
$TenantFilter = $Request.Body.tenantFilter

if (-not $Request.Body.UserId) {
return ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::BadRequest
Body = @{ Results = 'UserId is required' }
})
}

try {
$Result = Set-CIPPThing -UserId $Request.Body.UserId -TenantFilter $TenantFilter -Headers $Headers
$StatusCode = [HttpStatusCode]::OK
} catch {
$ErrorMessage = Get-CippException -Exception $_
$Result = "Failed to update thing: $($ErrorMessage.NormalizedError)"
Write-LogMessage -headers $Headers -API 'ExecThing' -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage
$StatusCode = Get-CippErrorStatusCode -ErrorRecord $_
}

return ([HttpResponseContext]@{
StatusCode = $StatusCode
Body = @{ Results = $Result }
})
}
```

Response bodies:

- **Action endpoints** (`Add`/`Edit`/`Remove`/`Exec`): `Body = @{ Results = ... }`, where `Results` is a string or
an array of `@{ resultText = '...'; state = 'success' | 'error' }`. Use the same shape for errors. The UI reads
`Results` from error responses too.
- **List endpoints**: return the array itself: `Body = @($Data)`.
- Mark each per-item result with `state`. If `state` is missing, the UI has to guess severity from the text.

---

## Status codes

| Situation | Status |
| --- | --- |
| Success | `200 OK` (`202 Accepted` when work is queued) |
| Missing or invalid request input, or a request the business rules refuse | `400 BadRequest` |
| A resource the caller named does not exist (template, task, user to act on) | `404 NotFound` |
| A CIPP access check refuses the caller (role, allowed tenants, `Test-CIPPAccess`) | `403 Forbidden` |
| A Graph / Exchange / SharePoint / Azure / table call failed, or anything unexpected | `500 InternalServerError` |
| Several items acted on: all succeeded / some failed / all failed | `200` / `207 MultiStatus` / `500` |

Rules that follow from the table:

- **A catch never returns `OK`.** A failure that becomes "Failed ..." text inside a 200 is a bug.
`backend/Tests/Static/CatchBlockStatusCode.Tests.ps1` enforces this, with a short allow-list for deliberate fallbacks.
- **403 is only for CIPP's own access checks.** If Microsoft refuses the CIPP app in a customer tenant, that is an
upstream failure: return 500.
- **Upstream failures return 500, not 400.** The frontend does not retry 4xx, and 400 tells the caller their input was wrong.
- **Validate input before the `try`**, as an early `return` with `BadRequest` (or `NotFound`) inside an `if`. A
validation `throw` inside the `try` lands in the same catch as upstream failures, so it can't be told apart. The
OpenAPI generator marks a field required when an `if` body rejects it with `throw` or `BadRequest`, so keep the
guard as an `if`.
- **Multi-item endpoints** count what they were asked to act on and what failed, then return
`$StatusCode = Get-CippBulkStatusCode -Total $Total -Failed $Failed`. Use `$Failed++`, never `+=`. Only count real item
failures. An optional enrichment step that falls back to a default is not a failure. A List endpoint that loops
tenants follows the same rule: partial data is 207, nothing is 500.
- **Polled status endpoints and protocol endpoints** (JSON-RPC, OAuth token passthrough) can carry an error inside a
200 when the client depends on that. Leave them that way on purpose, and add them to the guard's allow-list with a reason.

---

## Helpers that endpoints call

A helper must let its caller tell an input problem apart from an upstream failure:

- Throw `[System.ArgumentException]::new('<message>')` for invalid input or a refused request.
- Throw `[System.Management.Automation.ItemNotFoundException]::new('<message>')` for a named resource that does not exist.
- Let upstream failures throw as they are.
- In the endpoint catch, `Get-CippErrorStatusCode -ErrorRecord $_` maps these to 400 / 404 / 500. It also looks inside
wrapped exceptions, because a script block run through a .NET method surfaces as
`MethodInvocationException -> RuntimeException -> ArgumentException`.
- A layer between the helper and the endpoint must not catch a typed exception and rethrow it as a string
(`throw "Failed: $($_.Exception.Message)"`). That loses the type.
- A helper that acts on several items returns one `[pscustomobject]@{ resultText = '...'; state = 'success' | 'error' }`
per item instead of swallowing failures into strings, so the caller can count them.
- Before changing what a helper returns or throws, read **every** caller. Scheduled and background callers
(`New-CIPPUserTask`, offboarding tasks, BEC containment, extension syncs) must keep collecting per-step results and
must not start aborting halfway.

---

## Frontend contract

- `ApiGetCall` / `ApiPostCall` do not retry 4xx (except 408 and 429). They retry 5xx shed responses (503) and do not
retry 500.
- Multi-row table actions (`CippApiDialog` with `multiPost: false`) send one request per row. A row that returns an
error is reported as `{ Results: [{ resultText, state: 'error' }] }` and the rest still run. `onResult` gets
`{ failed: true }` as its second argument for that row.
- `CippApiResults` renders `Results` / `resultText` / `error` from error responses. Axios treats 207 as success, and
each item's `state` decides how it is shown.
- When you change an endpoint's codes, grep `frontend/src` for `/api/<Name>`. A page that reads data only on success
needs `isError` handling (`getCippError(x.error)`) if it used to get its error inside a 200.

---

## OpenAPI

`backend/Config/openapi.json` is generated from the entrypoint AST (`build/tools/build-openapi.ps1`):

- Status codes are documented from every `[HttpStatusCode]::X` in the file.
- An endpoint that uses `Get-CippBulkStatusCode` gets 200, 207 and 500.
- Codes that only come from `Get-CippErrorStatusCode` are not visible to the generator. Write the 400/404 guards as
explicit `[HttpStatusCode]::BadRequest` / `NotFound` returns where you can.
- Ask the maintainer before regenerating the spec.

---

## Tests

- If `backend/Tests/Endpoint/Invoke-<Name>.Tests.ps1` exists, add a case for each status the change introduces.
- Pin a helper's new contract with `Should -Throw -ExceptionType ([System.ArgumentException])`, or by asserting its
per-item `state` results.
- Always run `Invoke-Pester -Path backend/Tests/Static` (it includes the catch-block guard).
8 changes: 7 additions & 1 deletion .github/agents/CIPP-Standard-Agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: CIPP Baseline Standard Builder
description: >
Builds new baseline standards for the CIPP Baselines engine: a definition JSON in
backend/Config/BaselineStandards, plus - only when the logic demands it - a prepare hook
and executor in backend/Modules/CIPPCore/Public/Baselines.
and executor in backend/Modules/CIPPBaselines/Public/PrepareHooks and /Executors.
---

# CIPP Baseline Standard Builder
Expand All @@ -16,6 +16,9 @@ You build **baseline standards** — the drift-first declarative standards that
for every standard; your job is only to describe **what to read, what compliant looks
like, and how to write it**.

Classic standards (`backend/Modules/CIPPStandards`, `Invoke-CIPPStandard<Name>`) are **bugfix-only**.
Every new standard, and any new behaviour for an existing one, is built here as a baseline.

Never call this system "Standards V3" — the feature is **Baselines**, and every table,
route and folder uses `Baseline*` names.

Expand Down Expand Up @@ -149,6 +152,9 @@ Data, never Compliant**.

- **One function per file.** Hook and executor are separate files. Never build arrays with
`+=` — use `[System.Collections.Generic.List[object]]`.
- Hooks and executors run for every tenant in every baseline run: follow the PowerShell hot-path rules in
`.github/copilot-instructions.md` (no `| Where-Object` / `| Select-Object -First` over cached rows, lookups built
once, CippJson for JSON).
- When porting a classic standard, the default is an **exact port of its wire behaviour**;
flag questionable classic behaviour instead of silently "improving" it. Deviations
require sign-off and get recorded in
Expand Down
Loading
Loading