feat(apim): APIM Policy Management — list APIs, assign templates, app…#32
Open
seiggy wants to merge 6 commits into
Open
feat(apim): APIM Policy Management — list APIs, assign templates, app…#32seiggy wants to merge 6 commits into
seiggy wants to merge 6 commits into
Conversation
…ly via SDK
Adds the policy engine's ability to manage APIM policies through a UI instead
of hand-edited XML files. Implements McNulty's architecture (Tier B: template
apply) end-to-end across infra, backend, frontend, and tests.
M1 — Read-only catalog
- GET /api/apim/apis, /apis/{id}/operations, /apis/{id}/policy
- GET /api/apim/apis/{id}/operations/{opId}/policy
M2 — Template library
- 5 templates under policies/templates/ (entra-jwt-ai, entra-jwt-ai-dlp,
subscription-key-ai, subscription-key-ai-dlp, entra-jwt-rest)
- {{placeholder}} substitution + template.json manifests
- GET /api/apim/templates
M3 — Apply flow
- POST /api/apim/apis/{id}/policy (and operation-scoped variant) — async 202
- DELETE /api/apim/apis/{id}/policy (and operation-scoped variant)
- Cosmos policy-assignment doc store (existing configuration container)
- SHA256 hash of generated XML; status transitions pending→applying→synced|failed
- Azure.ResourceManager.ApiManagement SDK via DefaultAzureCredential
M4 — UI (src/aipolicyengine-ui)
- New /apis page with tree view (APIs/operations), details panel,
assign-template modal with dynamic parameter form, 2s status polling,
clear-confirm flow, XML viewer
Infra (Terraform)
- Custom least-privilege APIM role with only apis/operations read + policies
read/write/delete (NOT Service Contributor)
- Role assignment to Container App managed identity
- APIM_RESOURCE_ID plumbed to Container App env via deterministic root local
(avoids compute<->gateway module cycle)
Tests
- 76 new tests (TemplateRendering, TemplateLibrary, PolicyAssignmentRepository,
ApplyOrchestrator, ApimManagementEndpoints) — 295 passed / 0 failed / 4 skipped
- Caught and fixed a strict-XML-parse bug in TemplateLibraryService that was
rejecting valid APIM policy-expression templates
Non-AI API usage limits (separate feature) is paused per Zack's call; the
draft XML lives at .squad/files/non-ai-paused/ until M2 templates are validated.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e nested config The Container App env var was named APIM_RESOURCE_ID (single underscore), but ASP.NET Core's EnvironmentVariablesConfigurationProvider only maps nested config keys (like Apim:ResourceId) from env vars with double underscores (Apim__ResourceId). At runtime the binding silently failed, leaving Apim:ResourceId empty and throwing InvalidOperationException from ApimCatalogService when the first request hit /api/apim/apis. Rename the Terraform env var to Apim__ResourceId so it binds correctly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Orchestration log: 2026-05-21T17-43-57Z-freamon.md (APIM_RESOURCE_ID → Apim__ResourceId hotfix) - Session log: 2026-05-21T17-43-57Z-apim-config-binding-fix.md - Merge decision into Active Decisions: ASP.NET Core nested config convention (double-underscore env vars) - Delete inbox file: freamon-apim-config-binding-fix.md - Cross-agent context: append to sydnor/history.md and kima/history.md All 295 tests pass. Audit complete: no other single-underscore ASP.NET Core nested-config mismatches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Root cause: the initial APIM bootstrap callback depended on operationsByApi while also resetting that state, which changed the callback identity and retriggered the mount effect. Fix: keep the latest operations map in a ref so loadInitialData can reconcile the current selection without depending on the mutable operationsByApi object. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Orchestration log: 2026-05-21T18-35-00Z-kima.md documents the infinite render loop fix - Session log: 2026-05-21T18-35-00Z-apis-render-loop-fix.md brief summary - Merged decision inbox: kima-apis-render-loop.md into decisions.md as 2026-05-21T18:35:00Z entry - Cross-agent update: appended render-loop skill note to bunk/history.md with test coverage suggestion - Deleted inbox file after merge Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- ApiTree: Add min-w-0 flex-1 truncate to API name, flex-shrink-0 on badge - ApiTree: Remove redundant serviceUrl display (path is sufficient) - ApiTree: Simplify operation rows - show method badge + urlTemplate only (removes duplicate verb text) - AssignTemplateForm: Add min-w-0 + truncate to param label, flex-shrink-0 on badges - AssignTemplateForm: Change param grid to sm:grid-cols-2 for better modal fit - Dialog: Add overflow-x-hidden to prevent horizontal scrollbar Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…ly via SDK
Adds the policy engine's ability to manage APIM policies through a UI instead of hand-edited XML files. Implements McNulty's architecture (Tier B: template apply) end-to-end across infra, backend, frontend, and tests.
M1 — Read-only catalog
M2 — Template library
M3 — Apply flow
M4 — UI (src/aipolicyengine-ui)
Infra (Terraform)
Tests
Non-AI API usage limits (separate feature) is paused per Zack's call; the draft XML lives at .squad/files/non-ai-paused/ until M2 templates are validated.